Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- module Compiler
- open Syntax
- open ILInstructions
- type PrimValue =
- | BoolVal of bool
- | IntVal of int
- type MetaData =
- { locals : Map<string, int>
- nextLocal : int }
- let initMetaData = { locals = Map.empty
- nextLocal = 0 }
- let rec evalExpr (meta : MetaData) expr =
- match expr with
- | ConstInt i -> [PushInt i]
- | Var name ->
- match Map.tryFind name meta.locals with
- | None -> failwith "Variable '%s' does not exist." name
- | Some(i) -> [LoadLocal i]
- | PrimOp ("+", lOper, rOper) -> evalNumericExpr meta Add lOper rOper
- | PrimOp ("-", lOper, rOper) -> evalNumericExpr meta Sub lOper rOper
- | PrimOp ("*", lOper, rOper) -> evalNumericExpr meta Mul lOper rOper
- | PrimOp ("/", lOper, rOper) -> evalNumericExpr meta Div lOper rOper
- | PrimOp (">", lOper, rOper) -> evalNumericExpr meta Gt lOper rOper
- | PrimOp ("<", lOper, rOper) -> evalNumericExpr meta Lt lOper rOper
- | Let(name, valExpr) -> evalLet meta name valExpr
- | FunCall (funName, arg) -> evalFunCall meta funName arg
- | If (ifExpr, thenExpr, elseExpr ) -> evalIf meta ifExpr thenExpr elseExpr
- | _ -> failwith "Syntax error"
- and evalNumericExpr meta op lOper rOper =
- let left = evalExpr meta lOper
- let right = evalExpr meta rOper
- op :: (right @ left)
- and evalLet meta name valExpr =
- let valInstr = evalExpr meta valExpr
- let storeInstr = StoreLocal meta.nextLocal
- let updatedMeta = { meta with locals = Map.add name meta.nextLocal meta.locals
- nextLocal = meta.nextLocal + 1}
- storeInstr :: valInstr
- and evalIf meta ifExpr thenExpr elseExpr =
- let ifInstr = evalExpr meta ifExpr
- let thenInstr = evalExpr meta thenExpr |> List.rev
- let elseInstr = evalExpr meta elseExpr |> List.rev
- Branch (thenInstr, elseInstr) :: ifInstr
- and evalFunCall meta name expr =
- let argument = evalExpr meta expr
- match name with
- | (Var "print") -> Print :: argument
- | (Var funName) -> [MethodCall (funName, argument)]
- | _ -> failwith "Syntax error: expected (Var name)"
- let evalFuncDef meta funcDefs =
- match funcDefs with
- | FuncDef (name, argName, expr) ->
- let storeInstr = StoreLocal meta.nextLocal
- let updatedMeta = { meta with locals = Map.add argName meta.nextLocal meta.locals
- nextLocal = meta.nextLocal + 1}
- let funcInstr = evalExpr updatedMeta expr |> List.rev
- Method(name, [argName], funcInstr)
- let evalProgram (meta : MetaData) program =
- match program with
- | Program (funcDefs, expr) ->
- let evaluatedFuncDefs = List.map (evalFuncDef meta) funcDefs |> List.rev
- let mainInstr = evalExpr meta expr |> List.rev
- Class ("Program", evaluatedFuncDefs @ [EntryMethod("Main", [], mainInstr)])
- let compile program =
- evalProgram initMetaData program
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement