Skip to content

Commit f62e9e8

Browse files
committed
implemented dynamic overloading of functions
1 parent 7c150bc commit f62e9e8

5 files changed

Lines changed: 34 additions & 34 deletions

File tree

ngc/ClrGenerator.fs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,18 +74,18 @@ let nearestOverload (clrType : Type) methodName types =
7474

7575
type ClrCallGenerator(context : Context, typeBuilder : TypeBuilder, clrType : Type, methodName : string, arguments : SExp list,
7676
gf : IGeneratorFactory) =
77+
let args_seq = gf.MakeSequence context arguments
78+
let arg_types = args_seq.ReturnTypes()
79+
let clrMethod = nearestOverload clrType methodName arg_types
7780
interface IGenerator with
7881
member this.Generate ilGen =
79-
let args_seq = gf.MakeSequence context arguments
80-
let arg_types = args_seq.ReturnTypes()
81-
let clrMethod = nearestOverload clrType methodName arg_types
82+
8283
args_seq.Generate ilGen
8384
ilGen.Emit(OpCodes.Call, Option.get clrMethod)
85+
if (Option.get clrMethod).ReturnType = typeof<Void> then
86+
ilGen.Emit(OpCodes.Ldnull);
8487
member this.ReturnTypes() =
85-
let args_seq = gf.MakeSequence context arguments
86-
let arg_types = args_seq.ReturnTypes()
87-
let clrMethod = nearestOverload clrType methodName arg_types
88-
[(Option.get clrMethod).ReturnType]
88+
if (Option.get clrMethod).ReturnType = typeof<Void> then [typeof<obj>] else [(Option.get clrMethod).ReturnType]
8989

9090
type InstanceCallGenerator(context : Context, typeBuilder : TypeBuilder, instance : SExp, methodName : string, arguments : SExp list, gf : IGeneratorFactory) =
9191
interface IGenerator with

ngc/Context.fs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,22 @@ open Naggum.Compiler.Reader
2929

3030
type ContextValue =
3131
|Local of LocalBuilder * Type
32-
|Arg of int
32+
|Arg of int * Type
3333

3434
type Context =
3535
val types : Dictionary<string,Type>
36-
val functions : Dictionary<string, MethodInfo>
36+
val functions : Dictionary<string, (Type list -> MethodInfo)>
3737
val locals : Dictionary<string,ContextValue>
3838
new (t,f,l) =
3939
{types = t; functions = f; locals = l}
4040
new (ctx : Context) =
4141
let t = new Dictionary<string, Type>(ctx.types)
42-
let f = new Dictionary<string, MethodInfo>(ctx.functions)
42+
let f = new Dictionary<string, (Type list -> MethodInfo)>(ctx.functions)
4343
let l = new Dictionary<string,ContextValue>(ctx.locals)
4444
new Context (t,f,l)
4545
new() =
4646
let t = new Dictionary<string, Type>()
47-
let f = new Dictionary<string, MethodInfo>()
47+
let f = new Dictionary<string, (Type list -> MethodInfo)>()
4848
let l = new Dictionary<string,ContextValue>()
4949
new Context (t,f,l)
5050

ngc/FormGenerator.fs

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,16 @@ type SymbolGenerator(context:Context,name:string) =
4848
try
4949
let ctxval = context.locals.[name]
5050
match ctxval with
51-
|Local (local, t) ->
51+
|Local (local, _) ->
5252
ilGen.Emit(OpCodes.Ldloc,local)
53-
|Arg index ->
53+
|Arg (index,_) ->
5454
ilGen.Emit(OpCodes.Ldarg,(int16 index))
5555
with
5656
| :? KeyNotFoundException -> failwithf "Symbol %A not bound." name
5757
member this.ReturnTypes () =
5858
match context.locals.[name] with
5959
|Local (_,t) -> [t]
60-
|Arg _ -> [typeof<obj>]
60+
|Arg (_,t) -> [t]
6161

6262

6363
type SequenceGenerator(context:Context,typeBuilder:TypeBuilder,seq:SExp list, gf:IGeneratorFactory) =
@@ -179,32 +179,33 @@ type FullIfGenerator(context:Context,typeBuilder:TypeBuilder,condition:SExp,if_t
179179
List.concat (Seq.ofList [true_ret_type; false_ret_type]) //TODO This should return closest common ancestor of these types
180180

181181
type FunCallGenerator(context:Context,typeBuilder:TypeBuilder,fname:string,arguments:SExp list,gf:IGeneratorFactory) =
182+
let args_seq = gf.MakeSequence context arguments
183+
let func = context.functions.[fname] <| args_seq.ReturnTypes()
182184
interface IGenerator with
183185
member this.Generate ilGen =
184-
let func = context.functions.[fname]
185-
let args_seq = gf.MakeSequence context arguments
186-
let arg_types = args_seq.ReturnTypes()
187186
args_seq.Generate ilGen
188187
ilGen.Emit(OpCodes.Call,func)
189188
member this.ReturnTypes () =
190-
let func = context.functions.[fname]
191189
[func.ReturnType]
192190

193191
type DefunGenerator(context:Context,typeBuilder:TypeBuilder,fname:string,parameters:SExp list,body:SExp list,gf:IGeneratorFactory) =
192+
do context.functions.[fname] <- (fun arg_types ->
193+
let methodGen = typeBuilder.DefineMethod(fname, MethodAttributes.Public ||| MethodAttributes.Static, typeof<obj>, (Array.ofList arg_types))
194+
let methodILGen = (methodGen.GetILGenerator())
195+
let fun_ctx = new Context(context)
196+
for parm in parameters do
197+
match parm with
198+
| Atom(Symbol parm_name) ->
199+
let parm_idx = (List.findIndex (fun (p) -> p = parm) parameters)
200+
fun_ctx.locals.[parm_name] <- Arg (parm_idx,arg_types.[parm_idx])
201+
| other -> failwithf "In function %A parameter definition:\nExpected: Atom(Symbol)\nGot: %A" fname parm
202+
let bodyGen = gf.MakeBody fun_ctx body
203+
bodyGen.Generate methodILGen
204+
methodILGen.Emit(OpCodes.Ret)
205+
methodGen :> MethodInfo)
194206
interface IGenerator with
195207
member this.Generate ilGen =
196-
let argsDef = Array.create (List.length parameters) typeof<obj>
197-
let methodGen = typeBuilder.DefineMethod(fname, MethodAttributes.Public ||| MethodAttributes.Static, typeof<obj>, argsDef)
198-
let methodILGen = (methodGen.GetILGenerator())
199-
context.functions.[fname] <- methodGen
200-
let fun_ctx = new Context(context)
201-
for parm in parameters do
202-
match parm with
203-
| Atom(Symbol parm_name) -> fun_ctx.locals.[parm_name] <- Arg (List.findIndex (fun (p) -> p = parm) parameters)
204-
| other -> failwithf "In function %A parameter definition:\nExpected: Atom(Symbol)\nGot: %A" fname parm
205-
let bodyGen = gf.MakeBody fun_ctx body
206-
bodyGen.Generate methodILGen
207-
methodILGen.Emit(OpCodes.Ret)
208+
()
208209
member this.ReturnTypes() =
209210
[typeof<Void>]
210211

ngc/Generator.fs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ let compile (source : Stream) (assemblyName : string) (fileName : string) (asmRe
6262

6363
prologue ilGenerator
6464
try
65-
Reader.parse fileName source |> List.iter (fun sexp ->
66-
let gen = gf.MakeGenerator context sexp
67-
gen.Generate ilGenerator)
65+
let body = Reader.parse fileName source
66+
let gen = gf.MakeBody context body
67+
gen.Generate ilGenerator
6868
with
6969
| ex -> printfn "File: %A\nForm: %A\nError: %A" fileName sexp ex.Source
7070

tests/test.naggum

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,5 @@
6262
(test-quote)
6363
(test-new)
6464
(test-cons)
65-
(test-quote)
6665
(test-instance-call)
6766
(test-math)

0 commit comments

Comments
 (0)