Math.txt 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. Math::Script NSIS plugin.
  2. C-like style scripting (operators at least).
  3. Tip1: plugin watches the case of the letters.
  4. Tip2: plugin makes almost no error checks. So YOU should check your script
  5. twice before run :)
  6. New HOW TO USE: run the MathTest.Exe, and try yourself. After spending
  7. some minutes your should be able to write your script by yourself.
  8. To include it to your NSIS script just insert that:
  9. Math::Script "YourScript1"
  10. Math::Script "YourScript2"
  11. Math::Script "YourScriptFinal"
  12. How to use it? Simple:
  13. Strcpy $0 "Brainsucker"
  14. Math::Script "a = 'Math'; B = 'Script'; r0 += ' wants to use ' + a + '::' + b +'!'"
  15. DetailPrint "$0"
  16. That string will fill r0 with some stuff.
  17. Here are some other samples:
  18. 10! (factorial, r0 will contain '10! = 362880'):
  19. r0 = '10! = ' + (1*2*3*4*5*6*7*8*9)
  20. the same:
  21. a = b = 1; #{++a <= 10, b = b*a}; r0 = (a-1) + '! = ' + b
  22. Some floating point:
  23. Strcpy $R0 "1e1"
  24. Math::Script "pi = 3.14159; R1 = 2*pi*R0; r0 = 'Length of circle with radius ' + R0 + ' is equal to ' + R1 + '.'"
  25. Detailprint "$0"
  26. Ok. Variables.
  27. NSIS: r0-r9 -> $0-$9. R0-R9 -> $R0-$R9.
  28. Also CL ($CMDLINE), ID ($INSTDIR), OD ($OUTDIR), LG ($LANG), ED ($EXEDIR).
  29. User definable: name starting from character, up to 28 letters long.
  30. Stacks. Two stacks are supported: NSIS stack and plugin's own stack. I see no
  31. reasons for using plugin stack, but if you will, remember - the plugin stores
  32. variables used at function to that stack before function execution, and restores
  33. after execution. Even less I recommend you to use NSIS stack. You should use it
  34. only for input/output.
  35. How to use? It's variable styled. Plugins stack is associated with S variable,
  36. and NSIS stack associated with NS variable. To push to stack just do "S=0" or
  37. "NS=0", to pop from stack "a=S" or "b=NS". Combined operations supported too:
  38. "S += 1.5" will increment value at the top of stack by 1.5.
  39. Supported types: int (in fact that is __int64), float (double in fact),
  40. string.
  41. Int: just numbers, may include sign.
  42. Float: -123.456, 123.456e-78, 123e-45
  43. String: something in quotes ("", '', ``).
  44. There is also an array type. It is actually a reference type, so if b is array
  45. and you will perform "a=b", the a and b will reference a single array.
  46. To create a copy of array, use ca func: dest = ca(source). Btw - you couldn't
  47. control dimensions of arrays - they are autosized.
  48. To declare array:
  49. a = {};
  50. To declare array and initialize some items with values:
  51. {"Hello!", "Use", "mixed types", 1.01e23, "like that" ,1234};
  52. To access array:
  53. a[index] = "Cool";
  54. Also [] operation could be used to strings. str[x] gives you a single char with
  55. index x (zero-based) as new string. str[-x] - the same, but x counts from the
  56. string end (so the last char is -1). str[x,y] gives you characters in range x-y
  57. (inclusive), both x and y could be <0 - in this case they counted from the end
  58. of the string.
  59. The function could be useful - is conversion of arrays to strings and back.
  60. Example:
  61. a = a("Hello"); str = s(a);
  62. After running such script array a will contain 6 integers (chars and last zero
  63. - end of string), and str will contain your string back.
  64. Operators (some binary, some unary):
  65. >>= <<= -= += /= *= |= &= ^= %= -- ++ >> << && || <= =< >= => != ==
  66. = + - * / % < > & | ^ ~ !
  67. Only some are applicable to float (logic & arithmetic) and string (+ and logic)
  68. of course.
  69. Additional case: reference/de-reference operators (& and *). & will
  70. give you the reference to argument which should be a variable (NSIS, user, array
  71. item, stack), and * will convert it back to original variable. For example
  72. (a=&b; *a=10) will set b to 10. Expression (*&a) is equal to simple (a).
  73. Script is set of expressions (mathematical in general) delimited with ';'.
  74. Processing is mathematically right (2+2*2 will give 6), operations are performed
  75. in a C like order (precedence).
  76. Flow control:
  77. if-then-else like: #[if-expression, then-expr, else-expr]
  78. example:
  79. #[a==0, b=1; c=2, b *= (--c); c/=10]
  80. C eq:
  81. if (a==0) { b=1; c=2;} else { b*=(c++);c-=10; }
  82. while (expr) do; like #{expr, do}
  83. example:
  84. #{(c<1.1e25)&&(b < 10), b++; c*=1.23}
  85. C eq:
  86. while ((c<1.1e25)&&(b<10)) { b++; c*=1.23; }
  87. WATCH OUT! Comma (,) separates if-expr, then-expr, and else-expr from each
  88. other. All sub-expressions separated by (;) are the part of one expression,
  89. and the result of the last one of these sub-exprs gives you the result of
  90. expression.
  91. All the stuff (like variables and functions) will be saved between calls.
  92. Functions:
  93. type conversions:
  94. l(string) returns the length of string or array argument
  95. s(source) converts source to string type
  96. i(source) converts source to int type
  97. f(source) converts source to float type
  98. c(source) if source is string, returns int value of first
  99. char, if source is int, returns string which consists
  100. of a single char (source) (+0 terminator).
  101. a(source) converts source to array (only string supported)
  102. ff(float, format) converts float to string, with format
  103. options.
  104. options = precision + flags.
  105. Precision shows how many digits after decimal point
  106. will be shown. Flags:
  107. 16 (or 0x10) - No Exponential View
  108. (number will be shown as 123.123)
  109. 32 (or 0x20) - Only exponential view
  110. (number will be shown as 123.12e123)
  111. 64 (or 0x40) - use 'E' character instead of 'e'
  112. By default the plugin decides itself how to show your
  113. number.
  114. math (description of all these functions is available at MSDN, use the
  115. second given name for search):
  116. sin(x), sin Sine of argument
  117. cos(x), cos Cosine of argument
  118. cel(x), ceil Ceil of argument (no fract. part)
  119. csh(x), cosh Hyperbolic Cosine of Argument
  120. exp(x), exp Exponential
  121. abs(x), abs Absolute value (warning: float)
  122. flr(x), floor Floor of argument (no fract. part)
  123. asn(x), asin ArcSine of argument
  124. acs(x), acos ArcCosine of argument
  125. atn(x), atan ArcTangent of argument
  126. ln(x), log Exponential Logarithm
  127. log(x), log10 Decimal logarithm
  128. snh(x), sinh Hyperbolic Sine of Argument
  129. sqt(x), sqrt Square root of argument
  130. tan(x), tan Tangent of argument
  131. tnh(x), tanh Hyperbolic tangent of argument
  132. functions taking two arguments
  133. at2(x, y) atan2 Arctangent of the value (y/x)
  134. pow(x, y) pow power, x^y
  135. fmd(x, y) fmod floating point remainder
  136. fex(x, o) frexp Gets the mantissa (result = r)
  137. and exponent (o) of floating-point
  138. number (x): x = r*(2^o)
  139. mdf(x, o) modf Splits a floating-point value into
  140. fractional and integer parts.
  141. User-defined functions.
  142. It's very simple. Example:
  143. test(a,b) (a+b);
  144. After that test(1,2) will give you 3.
  145. test2(a,b) (a=a+b; b *= a);
  146. The result of function is always the result of last expression.
  147. As said before it better not to use stack (S) in between function calls.
  148. It will be better to develop variable-safe functions, i.e. functions which will
  149. not corrupt variables. For this you should either push/pop them to stack, or
  150. declare as additional arguments, which will never be used. Example:
  151. test3(a,b,c) (c=10; #{--c > 0, a=sqrt(a*b)}; a)
  152. No matter how many arguments will be passed to function, the values of all three
  153. vars (a,b,c) will be saved.
  154. Such variable-safe functions could be recursive:
  155. Math::Script 'rec(a) (#[a > 0, rec(a-1), 0]+a);'
  156. Math::Script 'R1 = rec(10)'
  157. will set R1 to right result 55.
  158. Sometimes functions will need to return more than one value, in this case you
  159. could declare argument as referent (b at example):
  160. test4(a, &b) (*b = a*a; a*a*a)
  161. In this case test4 will return a^3, and if we will call it like that test4(a,c),
  162. it will place a^2 to c. BUT! Note: you should use de-referencer (*) with variable,
  163. at example *b. CAUTION: never use the same variable as function internal reference
  164. variable and external argument variable (for example test4(a,b)). It will surely
  165. fail. Also: if you declared argument as reference - you should never supply
  166. a constant expression to it. It could be either array item (array[1]), NSIS
  167. register R0, any of the user variables (beside the variable with the same name:),
  168. but never the constant.
  169. Another may-be-useful possibility is to redeclare the function (the usual
  170. declaration at the time when function already defined will simply call that
  171. function). For such task you could use "#name", like "func()(1); #func()(2);".
  172. But beware, function declaration occurs at time of parsing, so it's not possible
  173. to perform flow controlled declaration.
  174. SUCH IS NOT POSSIBLE: "#[a<0, #func()(1), #func()(2)]"
  175. IT WILL SIMPLY DEFINE #func as (2), as the latest variant.
  176. (c) Nik Medved (brainsucker)