-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathExpressionNumbers.js
78 lines (72 loc) · 1.95 KB
/
ExpressionNumbers.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/**
* @flow
*/
import type {
Expression,
UserExpression,
} from './types';
import {
FuncCall,
Lambda,
UserFuncCall,
UserLambda,
UserVariable,
Variable,
} from './types';
export const tryExpressionForNumber = (defName: string): ?Expression => {
if (!isNumber(defName)) {
return null;
}
const num = Number(defName);
let body = Variable.make('z');
for (let i = 0; i < num; i++) {
body = FuncCall.make(Variable.make('s'), body);
}
return Lambda.make('s', Lambda.make('z', body));
};
export const tryUserExpressionForNumber = (defName: string): ?UserExpression => {
if (!isNumber(defName)) {
return null;
}
const num = Number(defName);
let body = UserVariable.make('z');
for (let i = 0; i < num; i++) {
body = UserFuncCall.make(UserVariable.make('s'), body);
}
return UserLambda.make('s', UserLambda.make('z', body));
};
export const isNumber = (defName: string): boolean => {
const num = Number(defName);
// The name must be a natural number in canonical form, so -5 and 03 are
// both disallowed.
return num >= 0 && ('' + num == defName);
};
/**
* Return true if the given number is too big.
*/
export const isGiantNumber = (defName: string): boolean => {
return isNumber(defName) && Number(defName) > 30;
};
export const tryResolveToNumber = (expr: Expression): ?string => {
if (!(expr instanceof Lambda) || expr.varName !== 's') {
return null;
}
expr = expr.body;
if (!(expr instanceof Lambda) || expr.varName !== 'z') {
return null;
}
expr = expr.body;
let result = 0;
while (expr instanceof FuncCall) {
const {func, arg} = expr;
if (!(func instanceof Variable) || func.varName !== 's') {
return null;
}
expr = arg;
result++;
}
if (!(expr instanceof Variable) || expr.varName !== 'z') {
return null;
}
return '' + result;
};