Skip to content

Instantly share code, notes, and snippets.

@rightfold

rightfold/.js Secret

Last active February 1, 2016 02:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rightfold/9e9ba03a02ea4ac3d60f to your computer and use it in GitHub Desktop.
Save rightfold/9e9ba03a02ea4ac3d60f to your computer and use it in GitHub Desktop.
let BoolType = {
format: function() {
return 'bool';
},
};
let IntType = {
format: function() {
return 'int';
},
};
function FunctionType(from, to) {
this.from = from;
this.to = to;
}
FunctionType.prototype.format = function() {
return '(' + this.from.map(t => t.format()).join(' ') + ' -> ' + this.to.map(t => t.format()).join(' ') + ')';
};
function NameExpression(name, type) {
this.name = name;
this._type = type;
}
NameExpression.prototype.format = function() {
return this.name;
};
NameExpression.prototype.type = function() {
return this._type;
};
function LambdaExpression(body) {
this.body = body;
}
LambdaExpression.prototype.format = function() {
return '{ ' + this.body.map(e => e.format()).join(' ') + ' }';
};
LambdaExpression.prototype.type = function() {
let from = [];
let to = [];
for (let expression of this.body) {
let expressionType = expression.type();
if (!(expressionType instanceof FunctionType)) {
throw Error('expected function but got ' + expressionType.format());
}
let hoistN = expressionType.from.length - to.length;
if (hoistN > 0) {
from = expressionType.from.slice(0, hoistN).concat(from);
}
to = to.slice(0, to.length - expressionType.from.length);
to = to.concat(expressionType.to);
console.log(Array((Error().stack.split('\n').length - 7) * 4).join(' '), expression.format(), ' / ', expressionType.format(), ' / ', new FunctionType(from, to).format());
}
return new FunctionType([], [new FunctionType(from, to)]);
};
{
console.group();
console.log('---------------- TEST CASE 1')
let expr = new LambdaExpression([
new NameExpression('mul', new FunctionType([IntType, IntType], [IntType])), // int
new NameExpression('dup', new FunctionType([IntType], [IntType, IntType])), // int int
new NameExpression('dup', new FunctionType([IntType], [IntType, IntType])), // int int int
new NameExpression('add', new FunctionType([IntType, IntType], [IntType])), // int int
new LambdaExpression([new NameExpression('add', new FunctionType([IntType, IntType], [IntType]))]), // int int (int int -> int)
new NameExpression('call', new FunctionType([IntType, IntType, new FunctionType([IntType, IntType], [IntType])], [IntType])), // int
]);
console.log(expr.format());
console.log(expr.type().format());
console.groupEnd();
}
{
console.group();
console.log('---------------- TEST CASE 2')
let expr = new LambdaExpression([
new NameExpression('dup', new FunctionType([IntType], [IntType, IntType])), // int int
new NameExpression('mul', new FunctionType([IntType, IntType], [IntType])), // int
]);
console.log(expr.format());
console.log(expr.type().format());
console.groupEnd();
}
{
console.group();
console.log('---------------- TEST CASE 3')
let expr = new LambdaExpression([
new NameExpression('id', new FunctionType([IntType], [IntType])), // int
new NameExpression('bla', new FunctionType([BoolType, IntType], [IntType])), // int
]);
console.log(expr.format());
console.log(expr.type().format());
console.groupEnd();
}
{
console.group();
console.log('---------------- TEST CASE 4')
let expr = new LambdaExpression([
new NameExpression('3', new FunctionType([], [IntType])), // int
new NameExpression('square', new FunctionType([IntType], [IntType])), // int
new NameExpression('print', new FunctionType([IntType], [])), //
]);
console.log(expr.format());
console.log(expr.type().format());
console.groupEnd();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment