module demo::lang::Pico::Typecheck
rascal-0.40.17
Usage
import demo::lang::Pico::Typecheck;
Dependencies
import Prelude;
import demo::lang::Pico::Abstract;
import demo::lang::Pico::Load;
alias TENV
tuple[ map[PicoId, TYPE] symbols, list[tuple[loc l, str msg]] errors]
function addError
TENV addError(TENV env, loc l, str msg) = env[errors = env.errors + <l, msg>];
function required
str required(TYPE t, str got) = "Required <getName(t)>, but got <got>";
str required(TYPE t1, TYPE t2) = required(t1, getName(t2));
function checkExp
Checking Expressions.
TENV checkExp(exp:natCon(int N), TYPE req, TENV env) = ❹
req := natural() ? env : addError(env, exp.src, required(req, "natural"));
TENV checkExp(exp:strCon(str S), TYPE req, TENV env) =
req := string() ? env : addError(env, exp.src, required(req, "string"));
TENV checkExp(exp:id(PicoId Id), TYPE req, TENV env) { ❺
if(!env.symbols[Id]?)
return addError(env, exp.src, "Undeclared variable <Id>");
tpid = env.symbols[Id];
return req := tpid ? env : addError(env, exp.src, required(req, tpid));
}
TENV checkExp(exp:add(EXP E1, EXP E2), TYPE req, TENV env) = ❻
natural() := req ? checkExp(E1, natural(), checkExp(E2, natural(), env))
: addError(env, exp.src, required(req, "natural"));
TENV checkExp(exp:sub(EXP E1, EXP E2), TYPE req, TENV env) = ❼
natural() := req ? checkExp(E1, natural(), checkExp(E2, natural(), env))
: addError(env, exp.src, required(req, "natural"));
TENV checkExp(exp:conc(EXP E1, EXP E2), TYPE req, TENV env) = ❽
string() := req ? checkExp(E1, string(), checkExp(E2, string(), env))
: addError(env, exp.src, required(req, "string"));
function checkStat
Check a statement.
TENV checkStat(stat:asgStat(PicoId Id, EXP Exp), TENV env) { ❾
if(!env.symbols[Id]?)
return addError(env, stat.src, "Undeclared variable <Id>");
tpid = env.symbols[Id];
return checkExp(Exp, tpid, env);
}
TENV checkStat(stat:ifElseStat(EXP Exp, ❶⓿
list[STATEMENT] Stats1,
list[STATEMENT] Stats2),
TENV env){
env0 = checkExp(Exp, natural(), env);
env1 = checkStats(Stats1, env0);
env2 = checkStats(Stats2, env1);
return env2;
}
TENV checkStat(stat:whileStat(EXP Exp,
list[STATEMENT] Stats1),
TENV env) {
env0 = checkExp(Exp, natural(), env);
env1 = checkStats(Stats1, env0);
return env1;
}
function checkStats
Check a list of statements.
TENV checkStats(list[STATEMENT] Stats1, TENV env) { ❶❶
for(S <- Stats1){
env = checkStat(S, env);
}
return env;
}
function checkDecls
Check declarations.
TENV checkDecls(list[DECL] Decls) = ❶❷
<( Id : tp | decl(PicoId Id, TYPE tp) <- Decls), []>;
function checkProgram
Check a Pico program.
TENV checkProgram(program(list[DECL] Decls, list[STATEMENT] Series)) { ❶❸
return checkStats(Series, checkDecls(Decls));
}
list[tuple[loc l, str msg]] checkProgram(str txt) = checkProgram(load(txt)).errors;