Skip to main content

module examples::ql::Checker

rascal-0.40.16
typepal-0.14.8

Usage

import examples::ql::Checker;

Source code

http://github.com/usethesource/typepal/src/examples/ql/Checker.rsc

Dependencies

import examples::ql::Syntax;
extend analysis::typepal::TypePal;

data AType

data AType  
= formType(str name)
| labelType()
| booleanType()
| integerType()
| stringType()
| moneyType()
;

function prettyAType

str prettyAType(formType(str name))     = "form <name>";

str prettyAType(labelType()) = "label";

str prettyAType(booleanType()) = "boolean";

str prettyAType(integerType()) = "integer";

str prettyAType(stringType()) = "string";

str prettyAType(moneyType()) = "money";

data IdRole

data IdRole  
= formId()
| labelId()
;

function collect

void collect(current: (Form) `form <Id name> { <Question* questions> }`, Collector c){
c.define("<name>", formId(), current, defType(formType("<name>")));
collect(questions, c);
}

void collect(current: (Question) `<Label label> <Var var> : <Type t> <Value? v>`, Collector c){
c.define("<label>", labelId(), label, defType(labelType()));
c.define("<var>", variableId(), var, defType(t));
for((Value) `[<Const const>]` <- v){
c.requireEqual(const, t, error(const, "Incompatible expression type %t, expected %t", const, t));
collect(const, c);
}
collect(t, c);
}

void collect(current: (Question) `<Label label> <Var var> : <Type t> = <Expr e> <Value? v>`, Collector c){
c.define("<label>", labelId(), label, defType(labelType()));
c.define("<var>", variableId(), var, defType(t));
c.requireEqual(e, t, error(e, "Incompatible expression type %t, expected %t", e, t));
for((Value) `[<Const const>]` <- v){
c.requireEqual(const, t, error(const, "Incompatible expression type %t, expected %t", const, t));
collect(const, c);
}
collect(t, e, c);
}

void collect(current: (Question) `if ( <Expr cond> ) <Question q>`, Collector c){
c.requireEqual(cond, booleanType(), error(cond, "Condition should be boolean, found %t", cond));
collect(cond, q, c);
}

void collect(current: (Question) `if ( <Expr cond> ) <Question q1> else <Question q2>`, Collector c){
c.requireEqual(cond, booleanType(), error(cond, "Condition should be boolean, found %t", cond));
collect(cond, q1, q2, c);
}

void collect(current: (Question) `{ <Question* questions> }`, Collector c){
collect(questions, c);
}

void collect(current: (Question) `( <Question* questions> )`, Collector c){
collect(questions, c);
}

void collect(current: (Expr) `<Id name>`, Collector c)
= c.use(name, {variableId()});

void collect(current: (Expr) `<Boolean boolean>`, Collector c)
= c.fact(current, booleanType());

void collect(current: (Expr) `<Integer integer>`, Collector c)
= c.fact(current, integerType());

void collect(current: (Expr) `<String integer>`, Collector c)
= c.fact(current, stringType());

void collect(current: (Expr) `<Money money>`, Collector c)
= c.fact(current, moneyType());

void collect(current: (Expr) `( <Expr e> )`, Collector c){
c.fact(current, e);
collect(e, c);
}

void collect(current: (Expr) `! <Expr e>`, Collector c){
c.fact(current, booleanType());
c.requireEqual(e, booleanType(), error(e, "boolean type expected, found %t", e));
collect(e, c);
}

function numericOp

void numericOp(Expr e, Expr e1, str op, Expr e2, Collector c){
c.calculate("numeric operator", e, [e1, e2],
AType(Solver s){
t1 = s.getType(e1); t2 = s.getType(e2);
s.requireTrue({t1,t2} <= {integerType(), moneyType()}, error(e, "Illegal arguments %t and %t for %q", t1, t2, op));
return (moneyType() in {t1, t2}) ? moneyType() : integerType();
});
collect(e1, e2, c);
}

function collect

void collect(current: (Expr) `<Expr e1> + <Expr e2>`, Collector c)  = numericOp(current, e1, "+", e2, c);

void collect(current: (Expr) `<Expr e1> - <Expr e2>`, Collector c) = numericOp(current, e1, "-", e2, c);

void collect(current: (Expr) `<Expr e1> * <Expr e2>`, Collector c) = numericOp(current, e1, "*", e2, c);

void collect(current: (Expr) `<Expr e1> / <Expr e2>`, Collector c) = numericOp(current, e1, "/", e2, c);

function comparisonOp

void comparisonOp(Expr e, Expr e1, str op, Expr e2, Collector c){
c.calculate("comparison operator", e, [e1, e2],
AType(Solver s){
s.requireTrue({s.getType(e1), s.getType(e2)} <= {integerType(), moneyType()},
error(e, "Illegal arguments %t and %t for %q", e1, e2, op));
return booleanType();
});
collect(e1, e2, c);
}

function collect

void collect(current: (Expr) `<Expr e1> \> <Expr e2>`, Collector c)  = comparisonOp(current, e1, "/\>", e2, c);

void collect(current: (Expr) `<Expr e1> \>= <Expr e2>`, Collector c) = comparisonOp(current, e1, "/\>=", e2, c);

void collect(current: (Expr) `<Expr e1> \< <Expr e2>`, Collector c) = comparisonOp(current, e1, "/\<", e2, c);

void collect(current: (Expr) `<Expr e1> \<= <Expr e2>`, Collector c) = comparisonOp(current, e1, "/\<=", e2, c);

function equalityOp

void equalityOp(Expr e, Expr e1, str op, Expr e2, Collector c){
c.calculate("(in)equality operator", e, [e1, e2],
AType(Solver s){
s.requireEqual(e1, e2, error(e, "Illegal arguments %t and %t for %q", e1, e2, op));
return booleanType();
});
collect(e1, e2, c);
}

function collect

void collect(current: (Expr) `<Expr e1> == <Expr e2>`, Collector c) = equalityOp(current, e1, "==", e2, c);

void collect(current: (Expr) `<Expr e1> != <Expr e2>`, Collector c) = equalityOp(current, e1, "!=", e2, c);

function boolOp

void boolOp(Expr e, Expr e1, str op, Expr e2, Collector c){
c.calculate("boolean operator", e, [e1, e2],
AType(Solver s){
s.requireEqual(e1, booleanType(), error(e1, "Illegal argument %t for %q", e1, op));
s.requireEqual(e2, booleanType(), error(e2, "Illegal argument %t for %q", e2, op));
return booleanType();
});
collect(e1, e2, c);
}

function collect

void collect(current: (Expr) `<Expr e1> && <Expr e2>`, Collector c) = boolOp(current, e1, "&&", e2, c);

void collect(current: (Expr) `<Expr e1> || <Expr e2>`, Collector c) = boolOp(current, e1, "||", e2, c);

void collect(current: Type t, Collector c){
c.fact(current, ("boolean" : booleanType(),
"integer" : integerType(),
"string" : stringType(),
"money" : moneyType())["<t>"]);
}

void collect(current: (Comment)`<CStart cstart> <CommentChar* commentChars> <CEnd cend>`, Collector c)
= collect(commentChars, c);

void collect(current: (Embed) `{ <Expr e> }`, Collector c)
= collect(e, c);