further opts
This commit is contained in:
+46
-47
@@ -60,7 +60,6 @@ Accepts the statement string `STMT` as the input line argument.
|
||||
7. Trim leading/trailing whitespace from `BODY`.
|
||||
8. If `KW` is equal to `GO` and the **third** non-whitespace character of `STMT` is equal to `S`, execute core language routine named `GOS` with `BODY` as a parameter and return.
|
||||
9. Execute core language routine with the name equal to the value of `KW` with `BODY` as a parameter and return.
|
||||
|
||||
## Number normalization function (`NORM`)
|
||||
|
||||
Accepts any number-like value `V` as the argument.
|
||||
@@ -68,7 +67,7 @@ Accepts any number-like value `V` as the argument.
|
||||
1. If `V` is an empty string, return 0 immediately.
|
||||
2. Convert `V` into an integer (by truncating the decimal part if necessary).
|
||||
3. If `V` is inside the allowed range (-32768 to 32767), return `V`.
|
||||
4. Set `V = V mod 65536`.
|
||||
4. Set `V = V % 65536`.
|
||||
5. If `V` exceeds 32767, set `V = V - 65536`.
|
||||
6. Return `V`.
|
||||
|
||||
@@ -76,56 +75,56 @@ Accepts any number-like value `V` as the argument.
|
||||
|
||||
Simple two-value evaluator. Accepts two stacks, value stack `VALSTACK` and operator stack `OPSTACK`.
|
||||
|
||||
1. Set the integer result `RES` to 0.
|
||||
2. Pop operation `OP` from `OPSTACK`.
|
||||
3. Pop operand `V2` from `VALSTACK`.
|
||||
4. Pop operand `V1` from `VALSTACK`.
|
||||
5. If `OP` is equal to `$`, set `RES` to a random value between 0 and `(V2 + 32768) % 32768`.
|
||||
6. If `OP` is equal to `+`, set `RES = V1 + V2`.
|
||||
7. If `OP` is equal to `-`, set `RES = V1 - V2`.
|
||||
8. If `OP` is equal to `*`, set `RES = V1 * V2`.
|
||||
9. If `OP` is equal to `/` and `V2` is not 0, set `RES = V1 / V2`.
|
||||
10. Push the value of `NORM(RES)` to `VALSTACK`.
|
||||
11. Return `VALSTACK` and `OPSTACK`.
|
||||
1. Pop operation `OP` from `OPSTACK`.
|
||||
2. Pop operand `V2` from `VALSTACK`.
|
||||
3. Pop operand `V1` from `VALSTACK`.
|
||||
4. If `OP` is equal to `$`, set `RES` to a random value between 0 and `(V2 + 32768) % 32768`.
|
||||
5. If `OP` is equal to `+`, set `RES = V1 + V2`.
|
||||
6. If `OP` is equal to `-`, set `RES = V1 - V2`.
|
||||
7. If `OP` is equal to `*`, set `RES = V1 * V2`.
|
||||
8. If `OP` is equal to `/` and `V2` is not 0, set `RES = V1 / V2`.
|
||||
9. Push the value of `NORM(RES)` to `VALSTACK`.
|
||||
10. Return `VALSTACK` and `OPSTACK`.
|
||||
|
||||
## Expression evaluation function (`EXPREVAL`)
|
||||
|
||||
Mathematical expression and intrinsic function application engine. Accepts a single `EXPR` string as a parameter.
|
||||
|
||||
1. Trim any leading/trailing whitespace from `EXPR`.
|
||||
2. If `EXPR` is empty, return 0 as a result.
|
||||
3. If `EXPR` only consists of digits, return `NORM(EXPR)` as a result.
|
||||
4. Substitute all occurrences of the string `RND` with the string `0$` inside `EXPR`.
|
||||
5. [Phase 1 start] Initialize a `PRE_EXPR` (prepared expression) string buffer with three opening parens `(((`.
|
||||
6. Initialize a previous character holder `PREVC` with an empty string.
|
||||
7. Fetch the next character `C` in `EXPR`. Go to step 15 if there are no more characters.
|
||||
8. If `C` is a digit or `$` character, append it to `PRE_EXPR` and go to step 14.
|
||||
9. If `C` is a variable name `A`-`Z`, append the value `VARS[C]` to `PRE_EXPR` and go to step 14.
|
||||
10. If `C` is an opening parenthesis `(`, append `(((` to `PRE_EXPR` and go to step 14.
|
||||
11. If `C` is a closing parenthesis `)`, append `)))` to `PRE_EXPR` and go to step 14.
|
||||
12. If `C` is either `*` or `/`, append `)`, then the value of `C`, then `(` to `PRE_EXPR` and go to step 14.
|
||||
13. If `C` is either `+` or `-`, check for the `PREVC` value. If `PREVC` is either an empty string or belongs to the `( + - * /` set, then append `0` and the value of `C` to `PRE_EXPR`, otherwise append `))`, then the value of `C`, then `((` to `PRE_EXPR`.
|
||||
14. Save the current value of `C` into `PREVC` and go to step 7.
|
||||
15. Append three closing parens `)))` to the end of `PRE_EXPR`.
|
||||
16. [Phase 2 start] Initialize a value buffer `VALBUF` as an empty string, and two empty stacks: `VALSTACK` and `OPSTACK`.
|
||||
17. Initialize precedence map `PRECMAP` with string keys and integer values. The map can be represented in JSON as follows: `{"+": 1, "-": 1, "*": 2, "/": 2, "$": 3}`.
|
||||
18. Fetch the next non-whitespace character `C` in `PRE_EXPR`. Go to step 33 if there are no more characters.
|
||||
19. If `C` is a digit, append it to `VALBUF` and go to step 18.
|
||||
20. If `VALBUF` is not empty, push its value onto `VALSTACK` and clear the `VALBUF` buffer.
|
||||
21. If `C` is an opening parenthesis `(`, push it onto `OPSTACK` and go to step 18.
|
||||
22. If `C` is a closing parenthesis `)`, go to step 23, otherwise go to step 25.
|
||||
23. While `OPSTACK` is not empty and the top of `OPSTACK` is not `(`, execute `EVALHELPER(VALSTACK,OPSTACK)`.
|
||||
24. If the top of `OPSTACK` is `(`, pop it from there. Go to step 18.
|
||||
25. If `C` is one of these `+ - * / $`, go to step 26, otherwise go to step 18.
|
||||
26. Set the current precedence value `PREC = PRECMAP[C]`.
|
||||
27. If `OPSTACK` is empty, go to step 32.
|
||||
28. Get the top operation on the `OPSTACK` without popping it. Assign it to `TOP_OP`.
|
||||
29. If `TOP_OP` is `(`, go to step 32.
|
||||
30. If `PRECMAP[TOP_OP] >= PREC`, execute `EVALHELPER(VALSTACK,OPSTACK)`, otherwise go to step 32.
|
||||
31. Go to step 27.
|
||||
32. Push `C` into `OPSTACK` and go to step 18.
|
||||
33. While `OPSTACK` is not empty, execute `EVALHELPER(VALSTACK,OPSTACK)`.
|
||||
34. Pop the value `RES` from `VALSTACK` and return `NORM(RES)` as the expression result.
|
||||
1. Trim leading/trailing whitespace from `EXPR`.
|
||||
2. If `EXPR` is empty, return 0.
|
||||
3. Initialize `VALSTACK` and `OPSTACK` as empty stacks.
|
||||
4. Initialize `VALBUF` and `PREVC` as empty strings.
|
||||
5. Set index `I = 0`.
|
||||
6. [Main Loop] Fetch character `C = EXPR[I]`. If out of bounds, go to step 16.
|
||||
7. If `C` is whitespace, increment `I` and go to step 6.
|
||||
8. If `C` is a digit:
|
||||
- Append `C` to `VALBUF`.
|
||||
- Set `PREVC = C`, increment `I`, go to step 6.
|
||||
9. If `VALBUF is not empty, push NORM(VALBUF) to VALSTACK and clear `VALBUF`.
|
||||
10. If EXPR[I onwards] starts with `RND`:
|
||||
- Push 0 to `VALSTACK`.
|
||||
- Set `C` to `$`.
|
||||
- Advance `I` by 3, go to step 14 (process `$` as operator).
|
||||
11. If `C` is a variable `A`-`Z`:
|
||||
- Push `NORM(VARS[C])` to `VALSTACK`.
|
||||
- Set `PREVC = C`, increment `I`, go to step 6.
|
||||
12. If `C` is `(`:
|
||||
- Push `(` to OPSTACK.
|
||||
- Set `PREVC = C`, increment `I`, go to step 6.
|
||||
13. If `C` is `)`:
|
||||
- While `OPSTACK` top is not `(`: Execute `EVALHELPER(VALSTACK, OPSTACK)`.
|
||||
- Pop `(` from `OPSTACK`.
|
||||
- Set `PREVC = C`, increment `I`, go to step 6.
|
||||
14. If `C` is an operator (`+ - * / $`):
|
||||
- If C is `+` or `-` AND (`PREVC` is empty OR belongs to `( + - * / $`):
|
||||
- Push 0 to `VALSTACK`.
|
||||
- While `OPSTACK` is not empty AND `PRECMAP[OPSTACK top] >= PRECMAP[C]`:
|
||||
- Execute `EVALHELPER(VALSTACK, OPSTACK)`.
|
||||
- Push `C` to `OPSTACK`.
|
||||
- Set `PREVC = C`, increment `I`, go to step 6.
|
||||
16. [Finalization] If `VALBUF` is not empty, push `NORM(VALBUF)` to `VALSTACK`.
|
||||
17. While `OPSTACK` is not empty: Execute `EVALHELPER(VALSTACK, OPSTACK)`.
|
||||
18. Return pop from `VALSTACK`.
|
||||
|
||||
## Core language routines
|
||||
|
||||
|
||||
Reference in New Issue
Block a user