Return = Struct.new(:loc, :type, :value)
Assert = Struct.new(:loc, :type, :value)
Const = Struct.new(:loc, :type, :value)
- Var = Struct.new(:loc, :type, :name)
+ Var = Struct.new(:loc, :type, :name, :module)
Def = Struct.new(:loc, :type, :name, :value)
Set = Struct.new(:loc, :type, :name, :value)
Op = Struct.new(:loc, :type, :op, :left, :right)
elsif tok.type == :ident
varname = IR::Var.new(tok.pos, nil, tok.text.to_sym)
if accept(".")
+ mod = syms[varname.name]
+ pp mod
+ if mod.kind != :module
+ error("accessing field in object that is neither a record nor a module")
+ end
tok = consume()
- field = IR::Var.new(tok.pos, nil, tok.text.to_sym)
- varname = make_binop(varname.loc, ".", varname, field)
+ sym = mod.type.exports[tok.text.to_sym]
+ if not sym
+ error("module or record has no such field '#{tok.text}'")
+ end
+ varname = IR::Var.new(tok.pos, sym[:type], tok.text.to_sym, varname.name)
end
varname
else
end
def infer_var(env, expr)
- if env[expr.name].nil?
- error(expr.loc, "symbol '#{expr.name}' not defined")
+ mod = expr.module
+ name = expr.name
+ if mod
+ expr.type = env[mod].type.exports[name][:type]
+ else
+ if env[expr.name].nil?
+ error(expr.loc, "symbol '#{expr.name}' not defined")
+ end
+ expr.type = env[expr.name][:type]
end
- expr.type = env[expr.name][:type]
+ expr.type
end
def infer_def(env, expr)
type = infer(env, expr.func)
end
- # Handle module references here
- if expr.func.type.is_a? Value::Module
- pp "MODULE!!!"
- pp expr
- end
-
error(expr.loc, "object being applied is not a function (has type: #{type.to_s})") if not type.is_a? Array
error(expr.loc, "wrong number of arguments to function call") if (type.length - 1) != expr.args.length
type[0..-2].each_with_index do |t,i|
end
def check_binary(env, expr, vtype)
- if expr.op == "."
- left_type = infer(env, expr.left)
- if not left_type.is_a? Value::Module
- error(expr.loc, "left side of '.' is not a module or record")
- end
- elsif expr.op == "["
+ if expr.op == "["
left_type = infer(env, expr.left)
if (left_type.is_a? Value::Type) and left_type.form == :array
check(env, expr.right, :int)