"true" => :bool,
"false" => :bool,
"if" => :if,
- "then" => :then,
"else" => :else,
- "end" => :end,
- "let" => :let,
- "func" => :func,
- "in" => :in,
- "set!" => :set,
+ "def" => :def,
+ "set" => :set,
+# "func" => :func,
+# "in" => :in,
"is" => :is,
"return" => :return,
}
Const = Struct.new(:loc, :type, :value)
Var = Struct.new(:loc, :type, :name)
Def = Struct.new(:loc, :type, :name, :value)
+ Set = Struct.new(:loc, :type, :name, :value)
Op = Struct.new(:loc, :type, :op, :left, :right)
Call = Struct.new(:loc, :type, :func, :args)
+ If = Struct.new(:loc, :type, :cond, :then, :else)
# EnvRef = Struct.new(:loc, :type, :index)
# Let = Struct.new(:loc, :type, :var, :expr, :body)
args = function_arglist()
func = IR::Func.new(name.loc, nil, args, [])
expect("{")
- expect(:return);
- if !matches("}")
- func.body << IR::Return.new(location, nil, expression())
- end
+ stmts = statement_list(["}", :return])
+ stmts << return_statement
+ func.body = stmts
expect("}");
func
end
IR::Var.new(name.pos, nil, name.text.to_sym)
end
+
+ ##
+ # Statements
+ ##
+ def statement_list(terminators)
+ stmts = []
+ while !matches_any(terminators)
+ stmts << statement
+ end
+ stmts
+ end
+
+ def statement()
+ # variable definition
+ # variable assignment
+ # if statement
+ # expression
+
+ if matches(:def)
+ variable_definition()
+ elsif matches(:set)
+ variable_assignment()
+ elsif matches(:if)
+ if_statement()
+ else
+ expression()
+ end
+ end
+
+ def return_statement()
+ loc = location
+ expect(:return);
+ if !matches("}")
+ IR::Return.new(loc, nil, expression())
+ else
+ IR::Return.new(loc, nil, nil)
+ end
+ end
+
+ def variable_definition()
+ loc = location
+ expect(:def)
+ name = identifier()
+ expect ("=")
+ value = expression()
+ IR::Def.new(loc, nil, name, value)
+ end
+
+ def variable_assignment()
+ loc = location
+ expect(:set)
+ name = identifier()
+ expect ("=")
+ value = expression()
+ IR::Set.new(loc, nil, name, value)
+ end
+
+ def if_statement()
+ loc = location
+ expect(:if)
+ cond = expression()
+ then_branch = statement_block()
+ if accept(:else)
+ if matches(:if)
+ else_branch = [ if_statement() ]
+ else
+ else_branch = statement_block()
+ end
+ end
+ IR::If.new(loc, nil, cond, then_branch, else_branch)
+ end
+
+ def statement_block()
+ loc = location
+ stmts = []
+ expect("{")
+ while !matches("}")
+ stmts << statement()
+ end
+ expect("}")
+ return stmts
+ end
+
+
+ ##
+ # Expressions
+ ##
+
def expression()
left = simple_expr()
if matches_any(["==", "!=", "<", "<=", ">", ">="])
emit_var(syms, v)
elsif v.is_a? IR::Call then
emit_call(syms, v)
+ elsif v.is_a? IR::Def then
+ emit_def(syms, v)
+ elsif v.is_a? IR::Set then
+ emit_set(syms, v)
+ elsif v.is_a? IR::If then
+ emit_if(syms, v)
else
raise "code emitting of #{v.class} not implemented"
end
def self.emit_var(syms, v)
sym = syms[v.name]
- if sym.kind == :param
- puts " get_param #{sym.value}"
+ if sym
+ if sym.kind == :param
+ puts " get_param #{sym.value}"
+ elsif sym.kind == :local
+ puts " get_local :#{sym.name}"
+ end
+ else
+ puts "# invalid var #{v.name}"
end
end
puts " fcallv"
end
end
+
+ def self.emit_def(syms, v)
+ puts "# def #{v.name} = #{v}"
+ syms.add_sym(
+ v.name.name, v.loc, :local, v.type, v.value)
+ emit(syms, v.value)
+ puts " set_local :#{v.name.name}"
+ end
+
+ def self.emit_set(syms, v)
+ puts " set_local :#{v.name.name}"
+ end
+
+ def self.emit_if(syms, v)
+ puts "# if "
+ end
end
$parser = Parser.new("cerise.m")