Skip to content

Commit 60ff2e5

Browse files
committed
refactored main compiler routine
1 parent e4c9d34 commit 60ff2e5

1 file changed

Lines changed: 6 additions & 142 deletions

File tree

ngc/Generator.fs

Lines changed: 6 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -33,148 +33,10 @@ open Naggum.Runtime
3333

3434
open Context
3535

36-
//TODO: Shoot that putrid shit and throw it out.
37-
let rec private generate (context : Context) (typeBuilder : TypeBuilder) (ilGen : ILGenerator) (form : SExp) =
38-
match form with
39-
| List list ->
40-
match list with
41-
| (Atom (Symbol "defun") :: Atom (Symbol name) :: List args :: body) ->
42-
let argsDef = Array.create (List.length args) typeof<obj>
43-
let methodGen = typeBuilder.DefineMethod(name, MethodAttributes.Public ||| MethodAttributes.Static, typeof<obj>, argsDef)
44-
let methodILGen = (methodGen.GetILGenerator())
45-
generateBody context typeBuilder methodILGen body
46-
methodILGen.Emit(OpCodes.Ret)
47-
// Add function to context:
48-
context.functions.[name] <- methodGen
49-
| Atom (Symbol "if") :: condition :: if_true :: if_false :: [] -> //full if form
50-
generate context typeBuilder ilGen condition
51-
let if_true_lbl = ilGen.DefineLabel()
52-
let end_form = ilGen.DefineLabel()
53-
ilGen.Emit (OpCodes.Brtrue, if_true_lbl)
54-
generate context typeBuilder ilGen if_false
55-
ilGen.Emit (OpCodes.Br,end_form)
56-
ilGen.MarkLabel if_true_lbl
57-
generate context typeBuilder ilGen if_true
58-
ilGen.MarkLabel end_form
59-
| Atom (Symbol "if") :: condition :: if_true :: [] -> //reduced if form
60-
generate context typeBuilder ilGen condition
61-
let if_true_lbl = ilGen.DefineLabel()
62-
let end_form = ilGen.DefineLabel()
63-
ilGen.Emit (OpCodes.Brtrue, if_true_lbl)
64-
ilGen.Emit OpCodes.Ldnull
65-
ilGen.Emit (OpCodes.Br,end_form)
66-
ilGen.MarkLabel if_true_lbl
67-
generate context typeBuilder ilGen if_true
68-
ilGen.MarkLabel end_form
69-
| Atom (Symbol "let") :: bindings :: body -> //let form
70-
ilGen.BeginScope()
71-
let scope_subctx = new Context (context)
72-
match bindings with
73-
| List list ->
74-
for binding in list do
75-
match binding with
76-
| List [(Atom (Symbol name)); form] ->
77-
let local = ilGen.DeclareLocal(typeof<obj>)
78-
generate context typeBuilder ilGen form
79-
ilGen.Emit (OpCodes.Stloc,local)
80-
scope_subctx.locals.[name] <- Local (local, typeof<obj>)
81-
| other -> failwithf "In let bindings: Expected: (name (form))\nGot: %A\n" other
82-
| other -> failwithf "In let form: expected: list of bindings\nGot: %A" other
83-
generateBody scope_subctx typeBuilder ilGen body
84-
ilGen.EndScope()
85-
| Atom (Symbol fname) :: args -> //generic funcall pattern
86-
genApply fname context typeBuilder ilGen args
87-
| _ -> failwithf "%A not supported yet." list
88-
| Atom a ->
89-
let genf = new GeneratorFactory(typeBuilder) :> IGeneratorFactory
90-
let gen = genf.MakeGenerator context (Atom a)
91-
ignore (gen.Generate ilGen)
92-
| other -> failwithf "%A form not supported yet." other
93-
and private generateBody context (typeBuilder : TypeBuilder) (ilGen : ILGenerator) (body : SExp list) =
94-
match body with
95-
| [] ->
96-
ilGen.Emit(OpCodes.Ldnull)
97-
| [last] ->
98-
generate context typeBuilder ilGen last
99-
| sexp :: rest ->
100-
generate context typeBuilder ilGen sexp
101-
ilGen.Emit(OpCodes.Pop)
102-
generateBody context typeBuilder ilGen rest
103-
and private generateSeq context (typeBuilder : TypeBuilder) (ilGen : ILGenerator) (seq : SExp list) =
104-
match seq with
105-
| [] ->
106-
ilGen.Emit(OpCodes.Ldnull)
107-
| [last] ->
108-
generate context typeBuilder ilGen last
109-
| sexp :: rest ->
110-
generate context typeBuilder ilGen sexp
111-
generateBody context typeBuilder ilGen rest
112-
and private genApply (funcName : string) (context : Context) (typeBuilder : TypeBuilder) (ilGen : ILGenerator) (argList: SExp list) : unit =
113-
try
114-
let func = context.functions.[funcName]
115-
generateSeq context typeBuilder ilGen argList
116-
ilGen.Emit(OpCodes.Call, func)
117-
with
118-
| :? KeyNotFoundException -> failwithf "Function %A not found." funcName
119-
12036
let private prologue (ilGen : ILGenerator) =
12137
ilGen.BeginScope()
12238

12339
let private epilogue context typeBuilder (ilGen : ILGenerator) =
124-
(* let argGetter = typeof<Value>.GetMethod "get_EmptyList"
125-
let isAtomGetter = typeof<SExp>.GetMethod "get_IsAtom"
126-
let atomItemGetter = typeof<SExp>.GetNestedType("Atom").GetMethod "get_Item"
127-
let isNumberGetter = typeof<Value>.GetMethod "get_IsNumber"
128-
let numberItemGetter = typeof<Value>.GetNestedType("Number").GetMethod "get_Item" *)
129-
130-
//ilGen.Emit(OpCodes.Call, argGetter)
131-
genApply "main" context typeBuilder ilGen ([])
132-
(*
133-
// Analyze value returned from main:
134-
let sexp = ilGen.DeclareLocal(typeof<SExp>)
135-
let value = ilGen.DeclareLocal(typeof<Value>)
136-
137-
let returnZero = ilGen.DefineLabel()
138-
let ``return`` = ilGen.DefineLabel()
139-
140-
// Get SExp:
141-
ilGen.Emit(OpCodes.Castclass, typeof<SExp>)
142-
ilGen.Emit(OpCodes.Stloc, sexp.LocalIndex)
143-
144-
// Check whether SExp is SExp.Atom:
145-
ilGen.Emit(OpCodes.Ldloc, sexp.LocalIndex)
146-
ilGen.Emit(OpCodes.Call, isAtomGetter)
147-
ilGen.Emit(OpCodes.Brfalse, returnZero)
148-
149-
// Cast SExp to SExp.Atom:
150-
ilGen.Emit(OpCodes.Ldloc, sexp.LocalIndex)
151-
ilGen.Emit(OpCodes.Castclass, typeof<SExp>.GetNestedType("Atom"))
152-
153-
// Get Value:
154-
ilGen.Emit(OpCodes.Call, atomItemGetter)
155-
ilGen.Emit(OpCodes.Stloc, value.LocalIndex)
156-
157-
// Check whether Value is Number:
158-
ilGen.Emit(OpCodes.Ldloc, value.LocalIndex)
159-
ilGen.Emit(OpCodes.Call, isNumberGetter)
160-
ilGen.Emit(OpCodes.Brfalse, returnZero)
161-
162-
// Cast Value to Number:
163-
ilGen.Emit(OpCodes.Ldloc, value.LocalIndex)
164-
ilGen.Emit(OpCodes.Castclass, typeof<Value>.GetNestedType("Number"))
165-
166-
// Get float64 value:
167-
ilGen.Emit(OpCodes.Call, numberItemGetter)
168-
169-
// Convert to int32:
170-
ilGen.Emit(OpCodes.Conv_I4)
171-
ilGen.Emit(OpCodes.Br, ``return``)
172-
173-
ilGen.MarkLabel returnZero
174-
ilGen.Emit(OpCodes.Ldc_I4, 0)
175-
176-
ilGen.MarkLabel ``return``
177-
*)
17840
ilGen.Emit OpCodes.Ret
17941
ilGen.EndScope()
18042

@@ -200,10 +62,12 @@ let compile (source : StreamReader) (assemblyName : string) (fileName : string)
20062

20163
prologue ilGenerator
20264
while not source.EndOfStream do
203-
let sexp = Reader.parse source
204-
let gen = gf.MakeGenerator context sexp
205-
ignore(gen.Generate ilGenerator)
206-
//generate context typeBuilder ilGenerator sexp
65+
try
66+
let sexp = Reader.parse source
67+
let gen = gf.MakeGenerator context sexp
68+
gen.Generate ilGenerator
69+
with
70+
| ex -> printfn "File: %A\nForm: %A\nError: %A" fileName sexp ex.Source
20771

20872
epilogue context typeBuilder ilGenerator
20973

0 commit comments

Comments
 (0)