Advertisement
Guest User

Untitled

a guest
Apr 13th, 2015
189
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
F# 3.07 KB | None | 0 0
  1. module Compiler
  2. open Syntax
  3. open ILInstructions
  4.  
  5. type PrimValue =
  6.     | BoolVal of bool
  7.     | IntVal of int
  8.  
  9. type MetaData =
  10.     { locals : Map<string, int>
  11.       nextLocal : int }
  12.  
  13. let initMetaData = { locals = Map.empty
  14.                      nextLocal = 0 }
  15.  
  16. let rec evalExpr (meta : MetaData) expr =
  17.     match expr with
  18.     | ConstInt i                  -> [PushInt i]
  19.     | Var name                    ->
  20.         match Map.tryFind name meta.locals with
  21.         | None    -> failwith "Variable '%s' does not exist." name
  22.         | Some(i) -> [LoadLocal i]
  23.     | PrimOp ("+", lOper, rOper)        -> evalNumericExpr meta Add lOper rOper
  24.     | PrimOp ("-", lOper, rOper)        -> evalNumericExpr meta Sub lOper rOper
  25.     | PrimOp ("*", lOper, rOper)        -> evalNumericExpr meta Mul lOper rOper
  26.     | PrimOp ("/", lOper, rOper)        -> evalNumericExpr meta Div lOper rOper
  27.     | PrimOp (">", lOper, rOper)        -> evalNumericExpr meta Gt lOper rOper
  28.     | PrimOp ("<", lOper, rOper)        -> evalNumericExpr meta Lt lOper rOper
  29.     | Let(name, valExpr)                -> evalLet meta name valExpr
  30.     | FunCall (funName, arg)            -> evalFunCall meta funName arg
  31.     | If (ifExpr, thenExpr, elseExpr )  -> evalIf meta ifExpr thenExpr elseExpr
  32.     | _                                 -> failwith "Syntax error"  
  33.  
  34. and evalNumericExpr meta op lOper rOper =
  35.     let left = evalExpr meta lOper
  36.     let right = evalExpr meta rOper
  37.     op :: (right @ left)
  38.  
  39. and evalLet meta name valExpr =
  40.     let valInstr = evalExpr meta valExpr
  41.     let storeInstr = StoreLocal meta.nextLocal
  42.     let updatedMeta = { meta with locals = Map.add name meta.nextLocal meta.locals
  43.                                   nextLocal = meta.nextLocal + 1}
  44.     storeInstr :: valInstr
  45.  
  46. and evalIf meta ifExpr thenExpr elseExpr =
  47.     let ifInstr = evalExpr meta ifExpr
  48.     let thenInstr = evalExpr meta thenExpr |> List.rev
  49.     let elseInstr = evalExpr meta elseExpr |> List.rev
  50.     Branch (thenInstr, elseInstr) :: ifInstr
  51.  
  52. and evalFunCall meta name expr =
  53.     let argument = evalExpr meta expr
  54.     match name with
  55.     | (Var "print") -> Print :: argument
  56.     | (Var funName) -> [MethodCall (funName, argument)]
  57.     | _             -> failwith "Syntax error: expected (Var name)"      
  58.  
  59. let evalFuncDef meta funcDefs =
  60.     match funcDefs with
  61.     | FuncDef (name, argName, expr) ->  
  62.         let storeInstr = StoreLocal meta.nextLocal
  63.         let updatedMeta = { meta with locals = Map.add argName meta.nextLocal meta.locals
  64.                                       nextLocal = meta.nextLocal + 1}
  65.         let funcInstr = evalExpr updatedMeta expr |> List.rev
  66.         Method(name, [argName], funcInstr)
  67.  
  68. let evalProgram (meta : MetaData) program =
  69.     match program with
  70.     | Program (funcDefs, expr) ->
  71.         let evaluatedFuncDefs = List.map (evalFuncDef meta) funcDefs |> List.rev
  72.         let mainInstr = evalExpr meta expr |> List.rev
  73.         Class ("Program", evaluatedFuncDefs @ [EntryMethod("Main", [],  mainInstr)])
  74.  
  75. let compile program =
  76.     evalProgram initMetaData program
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement