|
1 | 1 | module Naggum.Assembler.Assembler |
2 | 2 |
|
| 3 | +open System |
3 | 4 | open System.Reflection.Emit |
4 | 5 |
|
| 6 | +open Naggum.Assembler.Representation |
5 | 7 | open Naggum.Compiler |
| 8 | +open Naggum.Compiler.Reader |
| 9 | + |
| 10 | +let processMetadataItem = function |
| 11 | + | Atom (Symbol ".entrypoint") -> EntryPoint |
| 12 | + | other -> failwithf "Unrecognized metadata item definition: %A" other |
| 13 | + |
| 14 | +let processInstruction = function |
| 15 | + | List ([Atom (Symbol "ldstr"); Atom (Symbol string)]) -> Ldstr string |
| 16 | + | List ([Atom (Symbol "call"); Atom (Symbol methodName)]) -> failwithf "Method calls are not supported now" |
| 17 | + | List ([Atom (Symbol "ret")]) -> Ret |
| 18 | + | other -> failwithf "Unrecognized instruction: %A" other |
| 19 | + |
| 20 | +let addMetadata metadata method' = |
| 21 | + List.fold (fun ``method`` metadataExpr -> |
| 22 | + let metadataItem = processMetadataItem metadataExpr |
| 23 | + { ``method`` with Metadata = Set.add metadataItem ``method``.Metadata }) |
| 24 | + method' |
| 25 | + metadata |
| 26 | + |
| 27 | +let addBody body method' = |
| 28 | + List.fold (fun ``method`` bodyClause -> |
| 29 | + let instruction = processInstruction bodyClause |
| 30 | + { ``method`` with Body = List.append ``method``.Body [instruction] }) |
| 31 | + method' |
| 32 | + body |
| 33 | + |
| 34 | +let processAssemblyUnit = function |
| 35 | + | List (Atom (Symbol ".method") :: Atom (Symbol name) :: List arguments :: List metadata :: body) -> |
| 36 | + let definition = |
| 37 | + { Metadata = Set.empty |
| 38 | + Visibility = Public // TODO: Determine method visibility |
| 39 | + Name = name |
| 40 | + ReturnType = typeof<Void> // TODO: Determine method return type |
| 41 | + Body = List.empty } |
| 42 | + definition |
| 43 | + |> addMetadata metadata |
| 44 | + |> addBody body |
| 45 | + |> Method |
| 46 | + | other -> failwithf "Unrecognized assembly unit definition: %A" other |
| 47 | + |
| 48 | +let prepareTopLevel = function |
| 49 | + | List (Atom (Symbol ".assembly") :: Atom (Symbol name) :: units) -> |
| 50 | + { Name = name |
| 51 | + Units = List.map processAssemblyUnit units } |
| 52 | + | other -> failwithf "Unknown top-level construct: %A" other |
6 | 53 |
|
7 | 54 | /// Prepares the source file for assembling. Returns the intermediate |
8 | 55 | /// representation of the source code. |
9 | | -let prepare fileName stream = |
| 56 | +let prepare fileName stream : Assembly seq = |
10 | 57 | let forms = Reader.parse fileName stream |
11 | | - () |
| 58 | + forms |> Seq.map prepareTopLevel |
12 | 59 |
|
13 | 60 | /// Assembles the source code. Returns a list of assemblies ready for saving. |
14 | 61 | let assemble repr : AssemblyBuilder seq = |
|
0 commit comments