yukigo 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/.mocharc.json +4 -0
  2. package/CHANGELOG.md +6 -0
  3. package/README.md +199 -0
  4. package/dist/analyzer/index.d.ts +71 -0
  5. package/dist/analyzer/index.js +110 -0
  6. package/dist/analyzer/inspections/functional.d.ts +46 -0
  7. package/dist/analyzer/inspections/functional.js +123 -0
  8. package/dist/analyzer/inspections/generic.d.ts +151 -0
  9. package/dist/analyzer/inspections/generic.js +427 -0
  10. package/dist/analyzer/inspections/imperative.d.ts +37 -0
  11. package/dist/analyzer/inspections/imperative.js +105 -0
  12. package/dist/analyzer/inspections/logic.d.ts +49 -0
  13. package/dist/analyzer/inspections/logic.js +140 -0
  14. package/dist/analyzer/inspections/object.d.ts +83 -0
  15. package/dist/analyzer/inspections/object.js +235 -0
  16. package/dist/analyzer/utils.d.ts +4 -0
  17. package/dist/analyzer/utils.js +16 -0
  18. package/dist/index.d.ts +3 -0
  19. package/dist/index.js +3 -0
  20. package/dist/interpreter/components/EnvBuilder.d.ts +16 -0
  21. package/dist/interpreter/components/EnvBuilder.js +78 -0
  22. package/dist/interpreter/components/FunctionRuntime.d.ts +8 -0
  23. package/dist/interpreter/components/FunctionRuntime.js +52 -0
  24. package/dist/interpreter/components/LazyRuntime.d.ts +7 -0
  25. package/dist/interpreter/components/LazyRuntime.js +75 -0
  26. package/dist/interpreter/components/LogicEngine.d.ts +21 -0
  27. package/dist/interpreter/components/LogicEngine.js +152 -0
  28. package/dist/interpreter/components/LogicResolver.d.ts +11 -0
  29. package/dist/interpreter/components/LogicResolver.js +87 -0
  30. package/dist/interpreter/components/Operations.d.ts +14 -0
  31. package/dist/interpreter/components/Operations.js +69 -0
  32. package/dist/interpreter/components/PatternMatcher.d.ts +41 -0
  33. package/dist/interpreter/components/PatternMatcher.js +206 -0
  34. package/dist/interpreter/components/Visitor.d.ts +64 -0
  35. package/dist/interpreter/components/Visitor.js +299 -0
  36. package/dist/interpreter/errors.d.ts +19 -0
  37. package/dist/interpreter/errors.js +36 -0
  38. package/dist/interpreter/index.d.ts +32 -0
  39. package/dist/interpreter/index.js +44 -0
  40. package/dist/interpreter/utils.d.ts +14 -0
  41. package/dist/interpreter/utils.js +57 -0
  42. package/dist/utils/helpers.d.ts +14 -0
  43. package/dist/utils/helpers.js +51 -0
  44. package/package.json +30 -0
  45. package/src/analyzer/index.ts +132 -0
  46. package/src/analyzer/inspections/functional.ts +159 -0
  47. package/src/analyzer/inspections/generic.ts +499 -0
  48. package/src/analyzer/inspections/imperative.ts +129 -0
  49. package/src/analyzer/inspections/logic.ts +166 -0
  50. package/src/analyzer/inspections/object.ts +282 -0
  51. package/src/analyzer/utils.ts +26 -0
  52. package/src/index.ts +3 -0
  53. package/src/interpreter/components/EnvBuilder.ts +97 -0
  54. package/src/interpreter/components/FunctionRuntime.ts +79 -0
  55. package/src/interpreter/components/LazyRuntime.ts +97 -0
  56. package/src/interpreter/components/LogicEngine.ts +227 -0
  57. package/src/interpreter/components/LogicResolver.ts +130 -0
  58. package/src/interpreter/components/Operations.ts +81 -0
  59. package/src/interpreter/components/PatternMatcher.ts +254 -0
  60. package/src/interpreter/components/Visitor.ts +493 -0
  61. package/src/interpreter/errors.ts +47 -0
  62. package/src/interpreter/index.ts +59 -0
  63. package/src/interpreter/utils.ts +79 -0
  64. package/src/utils/helpers.ts +73 -0
  65. package/tests/analyzer/functional.spec.ts +221 -0
  66. package/tests/analyzer/generic.spec.ts +100 -0
  67. package/tests/analyzer/helpers.spec.ts +83 -0
  68. package/tests/analyzer/logic.spec.ts +292 -0
  69. package/tests/analyzer/oop.spec.ts +338 -0
  70. package/tests/interpreter/EnvBuilder.spec.ts +178 -0
  71. package/tests/interpreter/FunctionRuntime.spec.ts +234 -0
  72. package/tests/interpreter/LazyRuntime.spec.ts +190 -0
  73. package/tests/interpreter/LogicEngine.spec.ts +194 -0
  74. package/tests/interpreter/Operations.spec.ts +220 -0
  75. package/tests/interpreter/PatternSystem.spec.ts +189 -0
  76. package/tests/interpreter/interpreter.spec.ts +937 -0
  77. package/tsconfig.build.json +7 -0
  78. package/tsconfig.json +17 -0
@@ -0,0 +1,97 @@
1
+ import {
2
+ PrimitiveValue,
3
+ RangeExpression,
4
+ ConsExpression,
5
+ isLazyList,
6
+ LazyList,
7
+ } from "yukigo-ast";
8
+ import { createStream, ExpressionEvaluator } from "../utils.js";
9
+
10
+ export class LazyRuntime {
11
+ static realizeList(val: PrimitiveValue): PrimitiveValue[] {
12
+ if (Array.isArray(val)) return val;
13
+ if (isLazyList(val)) {
14
+ const result: PrimitiveValue[] = [];
15
+ const iter = val.generator();
16
+ let next = iter.next();
17
+ while (!next.done) {
18
+ if (next.value === undefined)
19
+ throw new Error("LazyList yielded undefined");
20
+ result.push(next.value);
21
+ next = iter.next();
22
+ }
23
+ return result;
24
+ }
25
+ throw new Error(`Expected List or LazyList, got ${typeof val}`);
26
+ }
27
+
28
+ static evaluateRange(
29
+ node: RangeExpression,
30
+ evaluator: ExpressionEvaluator,
31
+ config: any
32
+ ): PrimitiveValue {
33
+ const startVal = evaluator.evaluate(node.start);
34
+ if (typeof startVal !== "number")
35
+ throw new Error("Range start must be a number");
36
+
37
+ const hasEnd = node.end != null;
38
+
39
+ let step = 1;
40
+ if (node.step) {
41
+ const secondVal = evaluator.evaluate(node.step);
42
+ if (typeof secondVal !== "number")
43
+ throw new Error("Range step must be a number");
44
+ step = secondVal - startVal;
45
+ if (step === 0) throw new Error("Range step cannot be zero");
46
+ }
47
+
48
+ if (!hasEnd) {
49
+ return createStream(function* () {
50
+ let current = startVal;
51
+ while (true) {
52
+ yield current;
53
+ current += step;
54
+ }
55
+ });
56
+ }
57
+
58
+ const endVal = evaluator.evaluate(node.end);
59
+ if (typeof endVal !== "number")
60
+ throw new Error("Range end must be a number");
61
+
62
+ const result: number[] = [];
63
+ let current = startVal;
64
+ const cond = step > 0 ? () => current <= endVal : () => current >= endVal;
65
+
66
+ while (cond()) {
67
+ result.push(current);
68
+ current += step;
69
+ }
70
+ return result;
71
+ }
72
+
73
+ static evaluateCons(
74
+ node: ConsExpression,
75
+ evaluator: ExpressionEvaluator,
76
+ lazy: boolean
77
+ ): PrimitiveValue {
78
+ const head = evaluator.evaluate(node.head);
79
+ if (lazy) {
80
+ const tail = evaluator.evaluate(node.tail);
81
+ if (Array.isArray(tail)) return [head, ...tail];
82
+ if (isLazyList(tail))
83
+ return createStream(function* () {
84
+ yield head;
85
+ yield* tail.generator();
86
+ });
87
+
88
+ throw new Error(`Invalid tail type for Cons: ${typeof tail}`);
89
+ }
90
+
91
+ // Eager behavior
92
+ const tail = evaluator.evaluate(node.tail);
93
+ if (isLazyList(tail) || !Array.isArray(tail))
94
+ throw new Error("Expected Array in eager Cons");
95
+ return [head, ...tail];
96
+ }
97
+ }
@@ -0,0 +1,227 @@
1
+ import {
2
+ Exist,
3
+ Expression,
4
+ Findall,
5
+ Goal,
6
+ LiteralPattern,
7
+ Pattern,
8
+ PrimitiveValue,
9
+ Query,
10
+ SymbolPrimitive,
11
+ Variable,
12
+ VariablePattern,
13
+ } from "yukigo-ast";
14
+ import {
15
+ InternalLogicResult,
16
+ solveGoal,
17
+ Substitution,
18
+ success,
19
+ } from "./LogicResolver.js";
20
+ import { PatternResolver } from "./PatternMatcher.js";
21
+ import { EnvStack, InterpreterConfig } from "../index.js";
22
+ import { createStream, ExpressionEvaluator } from "../utils.js";
23
+ import { InterpreterError } from "../errors.js";
24
+
25
+ export class LogicEngine {
26
+ constructor(
27
+ private env: EnvStack,
28
+ private config: InterpreterConfig,
29
+ private evaluator: ExpressionEvaluator
30
+ ) {}
31
+
32
+ public solveQuery(node: Query): PrimitiveValue {
33
+ return this.evaluator.evaluate(node.expression);
34
+ }
35
+
36
+ public solveGoal(node: Goal): PrimitiveValue {
37
+ const patterns = node.args;
38
+ const generator = solveGoal(
39
+ this.env,
40
+ node.identifier.value,
41
+ patterns,
42
+ (body, substs) => this.solveConjunction(body, substs)
43
+ );
44
+ return this.handleOutputMode(generator);
45
+ }
46
+
47
+ public solveFindall(node: Findall): PrimitiveValue {
48
+ if (!(node.goal instanceof Goal))
49
+ throw new InterpreterError("solveFindall", "Findall expects a Goal");
50
+
51
+ const goalPatterns = node.goal.args.map((arg) => {
52
+ return this.expressionToPattern(arg);
53
+ });
54
+
55
+ const generator = solveGoal(
56
+ this.env,
57
+ node.goal.identifier.value,
58
+ goalPatterns,
59
+ (b, s) => this.solveConjunction(b, s)
60
+ );
61
+
62
+ const results: PrimitiveValue[] = [];
63
+ for (const res of generator)
64
+ results.push(this.instantiateTemplate(node.template, res.substs));
65
+
66
+ return results;
67
+ }
68
+
69
+ public solveExist(node: Exist): PrimitiveValue {
70
+ const generator = solveGoal(
71
+ this.env,
72
+ node.identifier.value,
73
+ node.patterns,
74
+ (body, substs) => this.solveConjunction(body, substs)
75
+ );
76
+ return this.handleOutputMode(generator);
77
+ }
78
+
79
+ private *solveConjunction(
80
+ expressions: Expression[],
81
+ substs: Substitution
82
+ ): Generator<InternalLogicResult> {
83
+ if (expressions.length === 0) {
84
+ yield success(substs);
85
+ return;
86
+ }
87
+
88
+ const [head, ...tail] = expressions;
89
+ let headGen: Generator<InternalLogicResult> | null = null;
90
+
91
+ if (head instanceof Goal) {
92
+ const args = head.args.map((arg) =>
93
+ this.instantiateExpressionAsPattern(arg, substs)
94
+ );
95
+ headGen = solveGoal(this.env, head.identifier.value, args, (b, s) =>
96
+ this.solveConjunction(b, s)
97
+ );
98
+ } else if (head instanceof Exist) {
99
+ const patterns = head.patterns.map((pat) =>
100
+ this.substitutePattern(pat, substs)
101
+ );
102
+ headGen = solveGoal(this.env, head.identifier.value, patterns, (b, s) =>
103
+ this.solveConjunction(b, s)
104
+ );
105
+ }
106
+
107
+ if (headGen) {
108
+ // backtracking
109
+ for (const headResult of headGen) {
110
+ const newSubsts = new Map([...substs, ...headResult.substs]);
111
+ yield* this.solveConjunction(tail, newSubsts);
112
+ }
113
+ } else {
114
+ // imperative
115
+ const result = this.evaluator.evaluate(head);
116
+ if (result) yield* this.solveConjunction(tail, substs);
117
+ }
118
+ }
119
+
120
+ private expressionToPattern(expr: Expression): Pattern {
121
+ if (expr instanceof VariablePattern) return expr;
122
+
123
+ if (expr instanceof Variable) {
124
+ const name = expr.identifier.value;
125
+ if (/^[A-Z_]/.test(name)) return new VariablePattern(expr.identifier);
126
+ }
127
+
128
+ try {
129
+ const val = this.evaluator.evaluate(expr);
130
+ return this.primitiveToPattern(val);
131
+ } catch (e) {
132
+ if (expr instanceof Variable) return new VariablePattern(expr.identifier);
133
+ throw e;
134
+ }
135
+ }
136
+
137
+ private primitiveToPattern(val: PrimitiveValue): Pattern {
138
+ if (
139
+ typeof val === "number" ||
140
+ typeof val === "string" ||
141
+ typeof val === "boolean"
142
+ )
143
+ return new LiteralPattern(new SymbolPrimitive(String(val)));
144
+
145
+ // TODO: Manejar arrays/listas complejas si es necesario
146
+ throw new InterpreterError(
147
+ "primitiveToPattern",
148
+ `Cannot convert value ${val} to Logic Pattern`
149
+ );
150
+ }
151
+
152
+ private instantiateExpressionAsPattern(
153
+ expr: Expression,
154
+ substs: Substitution
155
+ ): Pattern {
156
+ const patternBase = this.expressionToPattern(expr);
157
+ return this.substitutePattern(patternBase, substs);
158
+ }
159
+
160
+ private substitutePattern(
161
+ pat: Pattern,
162
+ substs: Substitution,
163
+ visited: Set<string> = new Set()
164
+ ): Pattern {
165
+ if (pat instanceof VariablePattern) {
166
+ const name = pat.name.value;
167
+ if (visited.has(name)) return pat;
168
+
169
+ const val = substs.get(name);
170
+ if (val) {
171
+ const newVisited = new Set(visited);
172
+ newVisited.add(name);
173
+ return this.substitutePattern(val, substs, newVisited);
174
+ }
175
+ }
176
+ return pat;
177
+ }
178
+
179
+ private instantiateTemplate(
180
+ template: Expression,
181
+ substs: Substitution
182
+ ): PrimitiveValue {
183
+ const pat = this.instantiateExpressionAsPattern(template, substs);
184
+ if (pat instanceof LiteralPattern) return this.evaluator.evaluate(pat.name);
185
+
186
+ throw new Error("Complex template instantiation not fully implemented");
187
+ }
188
+
189
+ private handleOutputMode(
190
+ gen: Generator<InternalLogicResult>
191
+ ): PrimitiveValue {
192
+ const mode = this.config.outputMode || "first";
193
+ switch (mode) {
194
+ case "stream": {
195
+ const self = this;
196
+ return createStream(function* () {
197
+ for (const res of gen) yield self.formatLogicResult(res.substs);
198
+ });
199
+ }
200
+ case "all": {
201
+ const res = [];
202
+ for (const r of gen) res.push(this.formatLogicResult(r.substs));
203
+ return res;
204
+ }
205
+ case "first": {
206
+ const next = gen.next();
207
+ if (next.done) return false;
208
+ return this.formatLogicResult(next.value.substs);
209
+ }
210
+
211
+ default:
212
+ throw new InterpreterError(
213
+ "handleOutputMode",
214
+ `Unsupported mode: ${mode}. Supported modes: all | stream | first`
215
+ );
216
+ }
217
+ }
218
+
219
+ private formatLogicResult(substs: Substitution): any {
220
+ const solutions = new Map<string, string>();
221
+ const resolver = new PatternResolver();
222
+ substs.forEach((pattern, key) => {
223
+ solutions.set(key, pattern.accept(resolver));
224
+ });
225
+ return { success: true, solutions };
226
+ }
227
+ }
@@ -0,0 +1,130 @@
1
+ import {
2
+ Expression,
3
+ Fact,
4
+ FunctorPattern,
5
+ Goal,
6
+ ListPattern,
7
+ LiteralPattern,
8
+ Pattern,
9
+ PrimitiveValue,
10
+ Rule,
11
+ VariablePattern,
12
+ WildcardPattern,
13
+ isRuntimePredicate,
14
+ } from "yukigo-ast";
15
+ import { EnvStack } from "../index.js";
16
+ import { lookup } from "../utils.js";
17
+ import { InterpreterError } from "../errors.js";
18
+
19
+ export type Substitution = Map<string, Pattern>;
20
+
21
+ export type InternalLogicResult = { success: true; substs: Substitution };
22
+
23
+ export type BodySolver = (
24
+ expressions: Expression[],
25
+ env: Substitution
26
+ ) => Generator<InternalLogicResult>;
27
+
28
+ export function success(substs: Substitution): InternalLogicResult {
29
+ return { success: true, substs };
30
+ }
31
+
32
+ function unifyParameters(
33
+ patterns: Pattern[],
34
+ args: Pattern[]
35
+ ): [Substitution, boolean] {
36
+ const subst: Substitution = new Map();
37
+ for (let i = 0; i < patterns.length; i++) {
38
+ const match = unify(patterns[i], args[i], subst);
39
+ if (!match) return [, false];
40
+ match.forEach((v, k) => subst.set(k, v));
41
+ }
42
+ return [subst, true];
43
+ }
44
+
45
+ export function* solveGoal(
46
+ envs: EnvStack,
47
+ predicateName: string,
48
+ args: Pattern[],
49
+ solveBody: BodySolver
50
+ ): Generator<InternalLogicResult> {
51
+ const pred = lookup(envs, predicateName);
52
+ if (!pred || !isRuntimePredicate(pred)) return;
53
+
54
+ for (const clause of pred.equations) {
55
+ if (clause.patterns.length !== args.length) continue;
56
+
57
+ const [substs, matches] = unifyParameters(clause.patterns, args);
58
+ if (!matches) continue;
59
+
60
+ if (clause instanceof Fact) {
61
+ yield success(substs);
62
+ continue;
63
+ }
64
+ if (clause instanceof Rule) {
65
+ const bodyGenerator = solveBody(clause.expressions, substs);
66
+ for (const finalResult of bodyGenerator)
67
+ yield success(finalResult.substs);
68
+ continue;
69
+ }
70
+ throw new InterpreterError(
71
+ "*solveGoal",
72
+ `Unexpected node: ${JSON.stringify(clause)}`
73
+ );
74
+ }
75
+ }
76
+
77
+ function resolve(node: Pattern, env: Substitution): Pattern {
78
+ if (node instanceof VariablePattern) {
79
+ const name = node.name.toString();
80
+ if (env.has(name)) return resolve(env.get(name), env);
81
+ }
82
+ return node;
83
+ }
84
+
85
+ export function unify(
86
+ t1: Pattern,
87
+ t2: Pattern,
88
+ argEnv?: Substitution
89
+ ): Substitution | null {
90
+ const env: Substitution = argEnv ?? new Map();
91
+ const r1 = resolve(t1, env);
92
+ const r2 = resolve(t2, env);
93
+
94
+ if (r1 === r2) return env;
95
+
96
+ if (r1 instanceof WildcardPattern || r2 instanceof WildcardPattern)
97
+ return env;
98
+
99
+ if (r1 instanceof VariablePattern) {
100
+ env.set(r1.name.value, r2);
101
+ return env;
102
+ }
103
+ if (r2 instanceof VariablePattern) {
104
+ env.set(r2.name.value, r1);
105
+ return env;
106
+ }
107
+
108
+ if (r1 instanceof LiteralPattern && r2 instanceof LiteralPattern)
109
+ return r1.name.equals(r2.name) ? env : null;
110
+
111
+ if (r1 instanceof FunctorPattern && r2 instanceof FunctorPattern) {
112
+ if (r1.identifier.value !== r2.identifier.value) return null;
113
+ if (r1.args.length !== r2.args.length) return null;
114
+
115
+ for (let i = 0; i < r1.args.length; i++) {
116
+ if (!unify(r1.args[i], r2.args[i], env)) return null;
117
+ }
118
+ return env;
119
+ }
120
+
121
+ if (r1 instanceof ListPattern && r2 instanceof ListPattern) {
122
+ if (r1.elements.length !== r2.elements.length) return null;
123
+ for (let i = 0; i < r1.elements.length; i++) {
124
+ if (!unify(r1.elements[i], r2.elements[i], env)) return null;
125
+ }
126
+ return env;
127
+ }
128
+
129
+ return null;
130
+ }
@@ -0,0 +1,81 @@
1
+ import { PrimitiveValue } from "yukigo-ast";
2
+ import { isArrayOfNumbers } from "../utils.js";
3
+
4
+ export type UnaryOp<T, R = T> = (x: T) => R;
5
+ export type BinaryOp<T, R = T> = (x: T, y: T) => R;
6
+ export type OperatorTable<T> = Record<string, T>;
7
+
8
+ export const ArithmeticBinaryTable: OperatorTable<BinaryOp<number>> = {
9
+ Plus: (a, b) => a + b,
10
+ Minus: (a, b) => a - b,
11
+ Multiply: (a, b) => a * b,
12
+ Divide: (a, b) => a / b,
13
+ Modulo: (a, b) => a % b,
14
+ Power: (a, b) => a ** b,
15
+ Min: (a, b) => Math.min(a, b),
16
+ Max: (a, b) => Math.max(a, b),
17
+ };
18
+
19
+ export const ComparisonOperationTable: OperatorTable<BinaryOp<boolean>> = {
20
+ Equal: (a, b) => a == b,
21
+ NotEqual: (a, b) => a != b,
22
+ Same: (a, b) => a === b,
23
+ NotSame: (a, b) => a !== b,
24
+ //Similar: (a, b) => ,
25
+ //NotSimilar: (a, b) => ,
26
+ GreaterOrEqualThan: (a, b) => a >= b,
27
+ GreaterThan: (a, b) => a > b,
28
+ LessOrEqualThan: (a, b) => a <= b,
29
+ LessThan: (a, b) => a < b,
30
+ };
31
+ export const LogicalBinaryTable: OperatorTable<
32
+ (l: boolean, r: () => boolean) => boolean
33
+ > = {
34
+ And: (left: boolean, rightThunk: () => boolean) => left && rightThunk(),
35
+ Or: (left: boolean, rightThunk: () => boolean) => left || rightThunk(),
36
+ };
37
+
38
+ export const BitwiseBinaryTable: OperatorTable<BinaryOp<number>> = {
39
+ BitwiseOr: (a, b) => a | b,
40
+ BitwiseAnd: (a, b) => a & b,
41
+ BitwiseLeftShift: (a, b) => a << b,
42
+ BitwiseRightShift: (a, b) => a >> b,
43
+ BitwiseUnsignedRightShift: (a, b) => a >>> b,
44
+ BitwiseXor: (a, b) => a ^ b,
45
+ };
46
+
47
+ export const StringOperationTable: OperatorTable<BinaryOp<string>> = {
48
+ Concat: (a, b) => `${a + b}`,
49
+ };
50
+
51
+ export const BitwiseUnaryTable: OperatorTable<UnaryOp<number>> = {
52
+ BitwiseNot: (a) => ~a,
53
+ };
54
+ export const LogicalUnaryTable: OperatorTable<UnaryOp<boolean>> = {
55
+ Negation: (a: boolean) => !a,
56
+ };
57
+ export const ListBinaryTable: OperatorTable<BinaryOp<PrimitiveValue[]>> = {
58
+ Concat: (a, b) => a.concat(b),
59
+ };
60
+ export const ListUnaryTable: OperatorTable<UnaryOp<PrimitiveValue[], PrimitiveValue>> = {
61
+ Size: (a: PrimitiveValue[]) => a.length,
62
+ DetectMax: (a: PrimitiveValue[]) => {
63
+ if (!isArrayOfNumbers(a))
64
+ throw new Error("Operand of DetectMax must be Array of numbers");
65
+ return Math.max(...a);
66
+ },
67
+ DetectMin: (a: PrimitiveValue[]) => {
68
+ if (!isArrayOfNumbers(a))
69
+ throw new Error("Operand of DetectMin must be Array of numbers");
70
+ return Math.min(...a);
71
+ },
72
+ Flatten: (a: PrimitiveValue[]) => a.flat(),
73
+ };
74
+ export const ArithmeticUnaryTable: OperatorTable<UnaryOp<number>> = {
75
+ Round: (a) => Math.round(a),
76
+ Absolute: (a) => Math.abs(a),
77
+ Ceil: (a) => Math.ceil(a),
78
+ Floor: (a) => Math.floor(a),
79
+ Negation: (a) => a * -1,
80
+ Sqrt: (a) => Math.sqrt(a),
81
+ };