From 3fc722bee0d2071c272dc91c5632ba77cfdbe1c8 Mon Sep 17 00:00:00 2001 From: Friedrich von Never Date: Sun, 27 Dec 2015 11:48:31 +0600 Subject: [PATCH] Project: convert CRLF to LF. --- .gitignore | 12 +- Naggum.Runtime/Naggum.Runtime.csproj | 104 ++--- Naggum.Runtime/Reader.cs | 306 +++++++------- Naggum.sln | 120 +++--- ngc/ClrGenerator.fs | 170 ++++---- ngc/Context.fs | 96 ++--- ngc/FormGenerator.fs | 594 +++++++++++++-------------- ngc/Generator.fs | 130 +++--- ngc/Globals.fs | 8 +- ngc/MathGenerator.fs | 94 ++--- ngc/MaybeMonad.fs | 22 +- ngc/Program.fs | 38 +- ngc/Reader.fs | 140 +++---- ngc/ngc.fsproj | 206 +++++----- 14 files changed, 1020 insertions(+), 1020 deletions(-) diff --git a/.gitignore b/.gitignore index 0bfcbd8..b880ac1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ -bin/ -obj/ -*.suo -/_ReSharper.Naggum/ -/*.user -/packages/ +bin/ +obj/ +*.suo +/_ReSharper.Naggum/ +/*.user +/packages/ diff --git a/Naggum.Runtime/Naggum.Runtime.csproj b/Naggum.Runtime/Naggum.Runtime.csproj index 0cb6973..6b44fd1 100644 --- a/Naggum.Runtime/Naggum.Runtime.csproj +++ b/Naggum.Runtime/Naggum.Runtime.csproj @@ -1,59 +1,59 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {402B5E79-E063-4833-AE4B-2986AEEC1D75} - Library - Properties - Naggum.Runtime - Naggum.Runtime - v4.6.1 - 512 - - - - true - full - false - ..\bin\ - DEBUG;TRACE - prompt - 4 - false - - - pdbonly - true - ..\bin\ - TRACE - prompt - 4 - false - - - - - - - - - - - - - - - - - + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {402B5E79-E063-4833-AE4B-2986AEEC1D75} + Library + Properties + Naggum.Runtime + Naggum.Runtime + v4.6.1 + 512 + + + + true + full + false + ..\bin\ + DEBUG;TRACE + prompt + 4 + false + + + pdbonly + true + ..\bin\ + TRACE + prompt + 4 + false + + + + + + + + + + + + + + + + + + --> \ No newline at end of file diff --git a/Naggum.Runtime/Reader.cs b/Naggum.Runtime/Reader.cs index dda66ff..e1a93eb 100644 --- a/Naggum.Runtime/Reader.cs +++ b/Naggum.Runtime/Reader.cs @@ -1,153 +1,153 @@ -using System; -using System.IO; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Naggum.Runtime -{ - public class Reader - { - /// - /// Checks if the character is constituent, i.e. not whitespace or list separator. - /// - /// character to be checked - /// true if the character is constituent, false otherwise - public static bool isConstituent(char c) - { - return (!Char.IsWhiteSpace(c)) - && c != '(' - && c != ')'; - } - - /// - /// Reads a symbol from a stream. - /// - /// stream to read from - /// - private static Object ReadSymbol(StreamReader reader) - { - bool in_symbol = true; - StringBuilder symbol_name = new StringBuilder(); - while (in_symbol) - { - var ch = reader.Peek(); - if (ch < 0) throw new IOException("Unexpected end of stream."); - if (isConstituent((char)ch)) - { - symbol_name.Append((char)reader.Read()); - } - else - { - in_symbol = false; - } - } - if (symbol_name.Length > 0) - return new Symbol(symbol_name.ToString()); - else - throw new IOException("Empty symbol."); - } - - /// - /// Reads a list from input stream. - /// - /// stream to read from - /// - private static Object ReadList(StreamReader reader) - { - bool in_list = true; - Stack list_stack = new Stack(); - Cons list = null; - while (in_list) - { - var ch = reader.Peek(); - if (ch < 0) throw new IOException("Unexpected end of stream."); - if ((char)ch != ')') - { - list_stack.Push(ReadObject(reader)); - } - else - { - reader.Read(); //consume closing paren - in_list = false; - } - } - while (list_stack.Count > 0) list = new Cons(list_stack.Pop(), list); - return list; - } - - /// - /// Reads a string from input stream - /// - /// input stream - /// a string that was read - private static string ReadString(StreamReader reader) - { - bool in_string = true; - bool single_escape = false; - StringBuilder sbld = new StringBuilder(); - - while (in_string) - { - var ch = reader.Read(); - if (single_escape) - { - single_escape = false; - switch (ch) - { - case 'n': sbld.Append('\n'); break; - case 'r': sbld.Append('\r'); break; - case '\"': sbld.Append('"'); break; - case 't': sbld.Append('\t'); break; - case '\\': sbld.Append('\\'); break; - default: throw new Exception("Unknown escape sequence: \\" + ch); - } - } - else - { - switch (ch) - { - case '\"': in_string = false; break; - case '\\': single_escape = true; break; - default: sbld.Append((char)ch); break; - } - } - - } - return sbld.ToString(); - } - - private static Object ReadObject(StreamReader reader) - { - while (Char.IsWhiteSpace((char)reader.Peek())) reader.Read(); //consume all leading whitespace - var ch = reader.Peek(); - if (ch < 0) return null; - if (ch == '(') //beginning of a list - { - reader.Read(); //consume opening list delimiter. - return ReadList(reader); - } - if (ch == '\"') //beginning of a string - { - reader.Read(); //consume opening quote - return ReadString(reader); - } - if (isConstituent((char)ch)) - return ReadSymbol(reader); - - throw new IOException("Unexpected char: " + (char)ch); - } - - /// - /// Reads an object from input stream. - /// - /// stream to read from - /// - public static Object Read(Stream stream) - { - StreamReader reader = new StreamReader(stream); - var obj = ReadObject(reader); - return obj; - } - } -} +using System; +using System.IO; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Naggum.Runtime +{ + public class Reader + { + /// + /// Checks if the character is constituent, i.e. not whitespace or list separator. + /// + /// character to be checked + /// true if the character is constituent, false otherwise + public static bool isConstituent(char c) + { + return (!Char.IsWhiteSpace(c)) + && c != '(' + && c != ')'; + } + + /// + /// Reads a symbol from a stream. + /// + /// stream to read from + /// + private static Object ReadSymbol(StreamReader reader) + { + bool in_symbol = true; + StringBuilder symbol_name = new StringBuilder(); + while (in_symbol) + { + var ch = reader.Peek(); + if (ch < 0) throw new IOException("Unexpected end of stream."); + if (isConstituent((char)ch)) + { + symbol_name.Append((char)reader.Read()); + } + else + { + in_symbol = false; + } + } + if (symbol_name.Length > 0) + return new Symbol(symbol_name.ToString()); + else + throw new IOException("Empty symbol."); + } + + /// + /// Reads a list from input stream. + /// + /// stream to read from + /// + private static Object ReadList(StreamReader reader) + { + bool in_list = true; + Stack list_stack = new Stack(); + Cons list = null; + while (in_list) + { + var ch = reader.Peek(); + if (ch < 0) throw new IOException("Unexpected end of stream."); + if ((char)ch != ')') + { + list_stack.Push(ReadObject(reader)); + } + else + { + reader.Read(); //consume closing paren + in_list = false; + } + } + while (list_stack.Count > 0) list = new Cons(list_stack.Pop(), list); + return list; + } + + /// + /// Reads a string from input stream + /// + /// input stream + /// a string that was read + private static string ReadString(StreamReader reader) + { + bool in_string = true; + bool single_escape = false; + StringBuilder sbld = new StringBuilder(); + + while (in_string) + { + var ch = reader.Read(); + if (single_escape) + { + single_escape = false; + switch (ch) + { + case 'n': sbld.Append('\n'); break; + case 'r': sbld.Append('\r'); break; + case '\"': sbld.Append('"'); break; + case 't': sbld.Append('\t'); break; + case '\\': sbld.Append('\\'); break; + default: throw new Exception("Unknown escape sequence: \\" + ch); + } + } + else + { + switch (ch) + { + case '\"': in_string = false; break; + case '\\': single_escape = true; break; + default: sbld.Append((char)ch); break; + } + } + + } + return sbld.ToString(); + } + + private static Object ReadObject(StreamReader reader) + { + while (Char.IsWhiteSpace((char)reader.Peek())) reader.Read(); //consume all leading whitespace + var ch = reader.Peek(); + if (ch < 0) return null; + if (ch == '(') //beginning of a list + { + reader.Read(); //consume opening list delimiter. + return ReadList(reader); + } + if (ch == '\"') //beginning of a string + { + reader.Read(); //consume opening quote + return ReadString(reader); + } + if (isConstituent((char)ch)) + return ReadSymbol(reader); + + throw new IOException("Unexpected char: " + (char)ch); + } + + /// + /// Reads an object from input stream. + /// + /// stream to read from + /// + public static Object Read(Stream stream) + { + StreamReader reader = new StreamReader(stream); + var obj = ReadObject(reader); + return obj; + } + } +} diff --git a/Naggum.sln b/Naggum.sln index a70824d..47bcfe1 100644 --- a/Naggum.sln +++ b/Naggum.sln @@ -1,60 +1,60 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test programs", "Test programs", "{2972575D-A421-4759-AE89-57560E0224AE}" - ProjectSection(SolutionItems) = preProject - tests\comment.naggum = tests\comment.naggum - tests\comment.result = tests\comment.result - tests\test.naggum = tests\test.naggum - tests\test.result = tests\test.result - EndProjectSection -EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "ngc", "ngc\ngc.fsproj", "{A4269C5E-E4AC-44BF-A06E-1B45248910AD}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Naggum.Runtime", "Naggum.Runtime\Naggum.Runtime.csproj", "{402B5E79-E063-4833-AE4B-2986AEEC1D75}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ngi", "ngi\ngi.csproj", "{34E781DF-EAD9-4034-ADE4-8DA41A16644A}" - ProjectSection(ProjectDependencies) = postProject - {402B5E79-E063-4833-AE4B-2986AEEC1D75} = {402B5E79-E063-4833-AE4B-2986AEEC1D75} - EndProjectSection -EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Naggum.Test", "Naggum.Test\Naggum.Test.fsproj", "{38230CBD-DE3E-4470-925F-DE966E8691AA}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution items", "Solution items", "{F85A1ACB-4A60-46A9-856D-92A3C9B97402}" - ProjectSection(SolutionItems) = preProject - .editorconfig = .editorconfig - .travis.yml = .travis.yml - appveyor.yml = appveyor.yml - License.md = License.md - Readme.md = Readme.md - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A4269C5E-E4AC-44BF-A06E-1B45248910AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A4269C5E-E4AC-44BF-A06E-1B45248910AD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A4269C5E-E4AC-44BF-A06E-1B45248910AD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A4269C5E-E4AC-44BF-A06E-1B45248910AD}.Release|Any CPU.Build.0 = Release|Any CPU - {402B5E79-E063-4833-AE4B-2986AEEC1D75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {402B5E79-E063-4833-AE4B-2986AEEC1D75}.Debug|Any CPU.Build.0 = Debug|Any CPU - {402B5E79-E063-4833-AE4B-2986AEEC1D75}.Release|Any CPU.ActiveCfg = Release|Any CPU - {402B5E79-E063-4833-AE4B-2986AEEC1D75}.Release|Any CPU.Build.0 = Release|Any CPU - {34E781DF-EAD9-4034-ADE4-8DA41A16644A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {34E781DF-EAD9-4034-ADE4-8DA41A16644A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {34E781DF-EAD9-4034-ADE4-8DA41A16644A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {34E781DF-EAD9-4034-ADE4-8DA41A16644A}.Release|Any CPU.Build.0 = Release|Any CPU - {38230CBD-DE3E-4470-925F-DE966E8691AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {38230CBD-DE3E-4470-925F-DE966E8691AA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {38230CBD-DE3E-4470-925F-DE966E8691AA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {38230CBD-DE3E-4470-925F-DE966E8691AA}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test programs", "Test programs", "{2972575D-A421-4759-AE89-57560E0224AE}" + ProjectSection(SolutionItems) = preProject + tests\comment.naggum = tests\comment.naggum + tests\comment.result = tests\comment.result + tests\test.naggum = tests\test.naggum + tests\test.result = tests\test.result + EndProjectSection +EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "ngc", "ngc\ngc.fsproj", "{A4269C5E-E4AC-44BF-A06E-1B45248910AD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Naggum.Runtime", "Naggum.Runtime\Naggum.Runtime.csproj", "{402B5E79-E063-4833-AE4B-2986AEEC1D75}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ngi", "ngi\ngi.csproj", "{34E781DF-EAD9-4034-ADE4-8DA41A16644A}" + ProjectSection(ProjectDependencies) = postProject + {402B5E79-E063-4833-AE4B-2986AEEC1D75} = {402B5E79-E063-4833-AE4B-2986AEEC1D75} + EndProjectSection +EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Naggum.Test", "Naggum.Test\Naggum.Test.fsproj", "{38230CBD-DE3E-4470-925F-DE966E8691AA}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution items", "Solution items", "{F85A1ACB-4A60-46A9-856D-92A3C9B97402}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + .travis.yml = .travis.yml + appveyor.yml = appveyor.yml + License.md = License.md + Readme.md = Readme.md + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A4269C5E-E4AC-44BF-A06E-1B45248910AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A4269C5E-E4AC-44BF-A06E-1B45248910AD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A4269C5E-E4AC-44BF-A06E-1B45248910AD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A4269C5E-E4AC-44BF-A06E-1B45248910AD}.Release|Any CPU.Build.0 = Release|Any CPU + {402B5E79-E063-4833-AE4B-2986AEEC1D75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {402B5E79-E063-4833-AE4B-2986AEEC1D75}.Debug|Any CPU.Build.0 = Debug|Any CPU + {402B5E79-E063-4833-AE4B-2986AEEC1D75}.Release|Any CPU.ActiveCfg = Release|Any CPU + {402B5E79-E063-4833-AE4B-2986AEEC1D75}.Release|Any CPU.Build.0 = Release|Any CPU + {34E781DF-EAD9-4034-ADE4-8DA41A16644A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {34E781DF-EAD9-4034-ADE4-8DA41A16644A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {34E781DF-EAD9-4034-ADE4-8DA41A16644A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {34E781DF-EAD9-4034-ADE4-8DA41A16644A}.Release|Any CPU.Build.0 = Release|Any CPU + {38230CBD-DE3E-4470-925F-DE966E8691AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {38230CBD-DE3E-4470-925F-DE966E8691AA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {38230CBD-DE3E-4470-925F-DE966E8691AA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {38230CBD-DE3E-4470-925F-DE966E8691AA}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/ngc/ClrGenerator.fs b/ngc/ClrGenerator.fs index f8a218b..bbfd310 100644 --- a/ngc/ClrGenerator.fs +++ b/ngc/ClrGenerator.fs @@ -1,86 +1,86 @@ -module ClrGenerator - -open System -open System.Reflection -open System.Reflection.Emit -open Naggum.Runtime -open Naggum.Compiler.Reader -open Naggum.Compiler.Context -open Naggum.Compiler.IGenerator -open Naggum.Util.MaybeMonad - -let nearestOverload (clrType : Type) methodName types = - let rec distanceBetweenTypes (derivedType : Type, baseType) = - match derivedType with - | null -> None - | someType - when someType = baseType -> Some 0 - | _ -> - maybe { - let! distance = distanceBetweenTypes (derivedType.BaseType, baseType) - return distance + 1 - } - let distance (availableTypes : Type list) (methodTypes : Type list) = - if availableTypes.Length <> methodTypes.Length then - None - else - Seq.zip availableTypes methodTypes - |> Seq.map distanceBetweenTypes - |> Seq.fold (fun state option -> - maybe { - let! stateNum = state - let! optionNum = option - return stateNum + optionNum - }) (Some 0) - let methods = clrType.GetMethods() |> Seq.filter (fun clrMethod -> clrMethod.Name = methodName) - let methodsAndDistances = methods - |> Seq.map (fun clrMethod -> clrMethod, - distance types (clrMethod.GetParameters() - |> Array.map (fun parameter -> - parameter.ParameterType) - |> Array.toList)) - |> Seq.filter (snd >> Option.isSome) - |> Seq.map (fun (clrMethod, distance) -> clrMethod, Option.get distance) - |> Seq.toList - if methodsAndDistances.IsEmpty then - None - else - let minDistance = methodsAndDistances |> List.minBy snd |> snd - let methods = methodsAndDistances |> List.filter (snd >> (fun d -> d = minDistance)) - |> List.map fst - if methods.IsEmpty then - None - else - Some (List.head methods) - -type ClrCallGenerator(context : Context, typeBuilder : TypeBuilder, clrType : Type, methodName : string, arguments : SExp list, - gf : IGeneratorFactory) = - let args_seq = gf.MakeSequence context arguments - let arg_types = args_seq.ReturnTypes() - let clrMethod = nearestOverload clrType methodName arg_types - interface IGenerator with - member this.Generate ilGen = - - args_seq.Generate ilGen - ilGen.Emit(OpCodes.Call, Option.get clrMethod) - member this.ReturnTypes() = - [(Option.get clrMethod).ReturnType] - -type InstanceCallGenerator(context : Context, typeBuilder : TypeBuilder, instance : SExp, methodName : string, arguments : SExp list, gf : IGeneratorFactory) = - interface IGenerator with - member this.Generate ilGen = - let inst_gen = gf.MakeGenerator context instance - let args_gen = gf.MakeSequence context arguments - let methodInfo = nearestOverload (inst_gen.ReturnTypes() |> List.head) methodName (args_gen.ReturnTypes()) - if Option.isSome methodInfo then - inst_gen.Generate ilGen - args_gen.Generate ilGen - ilGen.Emit(OpCodes.Callvirt,Option.get methodInfo) - else failwithf "No overload found for method %A with types %A" methodName (args_gen.ReturnTypes()) - member this.ReturnTypes () = - let inst_gen = gf.MakeGenerator context instance - let args_gen = gf.MakeSequence context arguments - let methodInfo = nearestOverload (inst_gen.ReturnTypes() |> List.head) methodName (args_gen.ReturnTypes()) - if Option.isSome methodInfo then - [(Option.get methodInfo).ReturnType] +module ClrGenerator + +open System +open System.Reflection +open System.Reflection.Emit +open Naggum.Runtime +open Naggum.Compiler.Reader +open Naggum.Compiler.Context +open Naggum.Compiler.IGenerator +open Naggum.Util.MaybeMonad + +let nearestOverload (clrType : Type) methodName types = + let rec distanceBetweenTypes (derivedType : Type, baseType) = + match derivedType with + | null -> None + | someType + when someType = baseType -> Some 0 + | _ -> + maybe { + let! distance = distanceBetweenTypes (derivedType.BaseType, baseType) + return distance + 1 + } + let distance (availableTypes : Type list) (methodTypes : Type list) = + if availableTypes.Length <> methodTypes.Length then + None + else + Seq.zip availableTypes methodTypes + |> Seq.map distanceBetweenTypes + |> Seq.fold (fun state option -> + maybe { + let! stateNum = state + let! optionNum = option + return stateNum + optionNum + }) (Some 0) + let methods = clrType.GetMethods() |> Seq.filter (fun clrMethod -> clrMethod.Name = methodName) + let methodsAndDistances = methods + |> Seq.map (fun clrMethod -> clrMethod, + distance types (clrMethod.GetParameters() + |> Array.map (fun parameter -> + parameter.ParameterType) + |> Array.toList)) + |> Seq.filter (snd >> Option.isSome) + |> Seq.map (fun (clrMethod, distance) -> clrMethod, Option.get distance) + |> Seq.toList + if methodsAndDistances.IsEmpty then + None + else + let minDistance = methodsAndDistances |> List.minBy snd |> snd + let methods = methodsAndDistances |> List.filter (snd >> (fun d -> d = minDistance)) + |> List.map fst + if methods.IsEmpty then + None + else + Some (List.head methods) + +type ClrCallGenerator(context : Context, typeBuilder : TypeBuilder, clrType : Type, methodName : string, arguments : SExp list, + gf : IGeneratorFactory) = + let args_seq = gf.MakeSequence context arguments + let arg_types = args_seq.ReturnTypes() + let clrMethod = nearestOverload clrType methodName arg_types + interface IGenerator with + member this.Generate ilGen = + + args_seq.Generate ilGen + ilGen.Emit(OpCodes.Call, Option.get clrMethod) + member this.ReturnTypes() = + [(Option.get clrMethod).ReturnType] + +type InstanceCallGenerator(context : Context, typeBuilder : TypeBuilder, instance : SExp, methodName : string, arguments : SExp list, gf : IGeneratorFactory) = + interface IGenerator with + member this.Generate ilGen = + let inst_gen = gf.MakeGenerator context instance + let args_gen = gf.MakeSequence context arguments + let methodInfo = nearestOverload (inst_gen.ReturnTypes() |> List.head) methodName (args_gen.ReturnTypes()) + if Option.isSome methodInfo then + inst_gen.Generate ilGen + args_gen.Generate ilGen + ilGen.Emit(OpCodes.Callvirt,Option.get methodInfo) + else failwithf "No overload found for method %A with types %A" methodName (args_gen.ReturnTypes()) + member this.ReturnTypes () = + let inst_gen = gf.MakeGenerator context instance + let args_gen = gf.MakeSequence context arguments + let methodInfo = nearestOverload (inst_gen.ReturnTypes() |> List.head) methodName (args_gen.ReturnTypes()) + if Option.isSome methodInfo then + [(Option.get methodInfo).ReturnType] else failwithf "No overload found for method %A with types %A" methodName (args_gen.ReturnTypes()) \ No newline at end of file diff --git a/ngc/Context.fs b/ngc/Context.fs index fd0a66d..ae4bfe2 100644 --- a/ngc/Context.fs +++ b/ngc/Context.fs @@ -1,48 +1,48 @@ -module Naggum.Compiler.Context - -open System -open System.Collections.Generic -open System.Reflection -open System.Reflection.Emit - -open Naggum.Runtime -open Naggum.Compiler.Reader - -type ContextValue = - |Local of LocalBuilder * Type - |Field of FieldBuilder * Type - |Arg of int * Type - -type Context = - val types : Dictionary - val functions : Dictionary MethodInfo)> - val locals : Dictionary - new (t,f,l) = - {types = t; functions = f; locals = l} - new (ctx : Context) = - let t = new Dictionary(ctx.types) - let f = new Dictionary MethodInfo)>(ctx.functions) - let l = new Dictionary(ctx.locals) - new Context (t,f,l) - new() = - let t = new Dictionary() - let f = new Dictionary MethodInfo)>() - let l = new Dictionary() - new Context (t,f,l) - - member public this.loadAssembly(asm:Assembly) = - let types = List.ofArray (asm.GetTypes()) - List.iter (fun (t:Type) -> this.types.Add(new Symbol(t.FullName),t)) types - - member public this.captureLocal(localName: Symbol, typeBuilder: TypeBuilder) = - let local = this.locals.[localName] - match local with - | Local (_,t) -> - let field = typeBuilder.DefineField(localName.Name,t,FieldAttributes.Static ||| FieldAttributes.Private) - this.locals.[localName] <- Field (field, t) - | Field (fb,_) -> () - | Arg (_,_) -> failwithf "Unable to capture parameter %A" localName.Name - -let create () = - let context = new Context() - context +module Naggum.Compiler.Context + +open System +open System.Collections.Generic +open System.Reflection +open System.Reflection.Emit + +open Naggum.Runtime +open Naggum.Compiler.Reader + +type ContextValue = + |Local of LocalBuilder * Type + |Field of FieldBuilder * Type + |Arg of int * Type + +type Context = + val types : Dictionary + val functions : Dictionary MethodInfo)> + val locals : Dictionary + new (t,f,l) = + {types = t; functions = f; locals = l} + new (ctx : Context) = + let t = new Dictionary(ctx.types) + let f = new Dictionary MethodInfo)>(ctx.functions) + let l = new Dictionary(ctx.locals) + new Context (t,f,l) + new() = + let t = new Dictionary() + let f = new Dictionary MethodInfo)>() + let l = new Dictionary() + new Context (t,f,l) + + member public this.loadAssembly(asm:Assembly) = + let types = List.ofArray (asm.GetTypes()) + List.iter (fun (t:Type) -> this.types.Add(new Symbol(t.FullName),t)) types + + member public this.captureLocal(localName: Symbol, typeBuilder: TypeBuilder) = + let local = this.locals.[localName] + match local with + | Local (_,t) -> + let field = typeBuilder.DefineField(localName.Name,t,FieldAttributes.Static ||| FieldAttributes.Private) + this.locals.[localName] <- Field (field, t) + | Field (fb,_) -> () + | Arg (_,_) -> failwithf "Unable to capture parameter %A" localName.Name + +let create () = + let context = new Context() + context diff --git a/ngc/FormGenerator.fs b/ngc/FormGenerator.fs index cfd0281..77387a6 100644 --- a/ngc/FormGenerator.fs +++ b/ngc/FormGenerator.fs @@ -1,297 +1,297 @@ -module Naggum.Compiler.FormGenerator - -open System -open System.Collections.Generic -open System.Reflection -open System.Reflection.Emit -open Naggum.Runtime -open Naggum.Compiler.Context -open Naggum.Compiler.IGenerator -open Naggum.Compiler.Reader - -type FormGenerator() = - interface IGenerator with - member this.Generate _ = failwith "Internal compiler error: unreified form generator invoked" - member this.ReturnTypes () = failwithf "Internal compiler error: inferring return type of unreified form" - -type ValueGenerator(context:Context,value:Value) = - inherit FormGenerator() - interface IGenerator with - member this.Generate _ = failwith "Internal compiler error: unreified value generator invoked" - member this.ReturnTypes () = failwithf "Internal compiler error: inferring return type of unreified value" - -type SymbolGenerator(context:Context,name:string) = - inherit ValueGenerator(context,Symbol name) - interface IGenerator with - member this.Generate ilGen = - try - let ctxval = context.locals.[new Symbol(name)] - match ctxval with - |Local (local, _) -> - ilGen.Emit(OpCodes.Ldloc,local) - |Arg (index,_) -> - ilGen.Emit(OpCodes.Ldarg,(int16 index)) - with - | :? KeyNotFoundException -> failwithf "Symbol %A not bound." name - member this.ReturnTypes () = - match context.locals.[new Symbol(name)] with - |Local (_,t) -> [t] - |Arg (_,t) -> [t] - - -type SequenceGenerator(context:Context,typeBuilder:TypeBuilder,seq:SExp list, gf:IGeneratorFactory) = - member private this.gen_seq (ilGen:ILGenerator,seq:SExp list) = - match seq with - | [] -> - () - | [last] -> - let gen = gf.MakeGenerator context last - gen.Generate ilGen - | sexp :: rest -> - let gen = gf.MakeGenerator context sexp - ignore (gen.Generate ilGen) - this.gen_seq (ilGen, rest) - interface IGenerator with - member this.Generate ilGen = this.gen_seq (ilGen,seq) - member this.ReturnTypes () = - List.map (fun (sexp) -> List.head ((gf.MakeGenerator context sexp).ReturnTypes())) seq - -type BodyGenerator(context : Context, - methodBuilder : MethodBuilder, - body : SExp list, - gf : IGeneratorFactory) = - let rec genBody (ilGen : ILGenerator) (body : SExp list) = - match body with - | [] -> - ilGen.Emit(OpCodes.Ldnull) - | [last] -> - let gen = gf.MakeGenerator context last - let stackType = List.head <| gen.ReturnTypes () - let returnType = methodBuilder.ReturnType - gen.Generate ilGen - match (stackType, returnType) with - | (s, r) when s = typeof && r = typeof -> () - | (s, r) when s = typeof && r <> typeof -> ilGen.Emit OpCodes.Ldnull - | (s, r) when s <> typeof && r = typeof -> ilGen.Emit OpCodes.Pop - | _ -> () - | sexp :: rest -> - let gen = gf.MakeGenerator context sexp - let val_type = gen.ReturnTypes() - gen.Generate ilGen - if List.head val_type <> typeof then - ilGen.Emit(OpCodes.Pop) - genBody ilGen rest - interface IGenerator with - member __.Generate ilGen = - genBody ilGen body - member this.ReturnTypes () = - match body with - |[] -> [typeof] - |somelist -> - let tail_type = (gf.MakeGenerator context (List.rev body |> List.head)).ReturnTypes() - if tail_type = [typeof] then - [typeof] - else tail_type - -type LetGenerator(context : Context, - typeBuilder : TypeBuilder, - methodBuilder : MethodBuilder, - bindings:SExp, - body : SExp list, - gf : IGeneratorFactory) = - interface IGenerator with - member this.Generate ilGen = - ilGen.BeginScope() - let scope_subctx = new Context (context) - match bindings with - | List list -> - for binding in list do - match binding with - | List [(Atom (Symbol name)); form] -> - let generator = gf.MakeGenerator scope_subctx form - let local_type = List.head (generator.ReturnTypes()) - let local = ilGen.DeclareLocal(local_type) - scope_subctx.locals.[new Symbol(name)] <- Local (local, local_type) - generator.Generate ilGen - ilGen.Emit (OpCodes.Stloc,local) - | other -> failwithf "In let bindings: Expected: (name (form))\nGot: %A\n" other - | other -> failwithf "In let form: expected: list of bindings\nGot: %A" other - let bodyGen = new BodyGenerator (scope_subctx, methodBuilder, body, gf) :> IGenerator - bodyGen.Generate ilGen - ilGen.EndScope() - member this.ReturnTypes () = - let type_subctx = new Context(context) - match bindings with - | List list -> - for binding in list do - match binding with - | List [(Atom (Symbol name)); form] -> - let generator = gf.MakeGenerator type_subctx form - type_subctx.locals.[new Symbol(name)] <- Local (null,generator.ReturnTypes() |> List.head) - | other -> failwithf "In let bindings: Expected: (name (form))\nGot: %A\n" other - | other -> failwithf "In let form: expected: list of bindings\nGot: %A" other - (gf.MakeBody type_subctx body).ReturnTypes() - -type ReducedIfGenerator(context:Context,typeBuilder:TypeBuilder,condition:SExp,if_true:SExp,gf:IGeneratorFactory) = - let returnTypes = (gf.MakeGenerator context if_true).ReturnTypes() - interface IGenerator with - member this.Generate ilGen = - let cond_gen = gf.MakeGenerator context condition - let if_true_gen = gf.MakeGenerator context if_true - let if_true_lbl = ilGen.DefineLabel() - let end_form = ilGen.DefineLabel() - cond_gen.Generate ilGen - ilGen.Emit (OpCodes.Brtrue, if_true_lbl) - - if List.head returnTypes <> typeof - then ilGen.Emit OpCodes.Ldnull - - ilGen.Emit (OpCodes.Br, end_form) - ilGen.MarkLabel if_true_lbl - if_true_gen.Generate ilGen - ilGen.MarkLabel end_form - member this.ReturnTypes () = - returnTypes - -type FullIfGenerator(context:Context,typeBuilder:TypeBuilder,condition:SExp,if_true:SExp,if_false:SExp,gf:IGeneratorFactory) = - interface IGenerator with - member this.Generate ilGen = - let cond_gen = gf.MakeGenerator context condition - let if_true_gen = gf.MakeGenerator context if_true - let if_false_gen = gf.MakeGenerator context if_false - let if_true_lbl = ilGen.DefineLabel() - let end_form = ilGen.DefineLabel() - ignore (cond_gen.Generate ilGen) - ilGen.Emit (OpCodes.Brtrue, if_true_lbl) - if_false_gen.Generate ilGen - ilGen.Emit (OpCodes.Br,end_form) - ilGen.MarkLabel if_true_lbl - if_true_gen.Generate ilGen - ilGen.MarkLabel end_form - member this.ReturnTypes () = - let true_ret_type = (gf.MakeGenerator context if_true).ReturnTypes() - let false_ret_type = (gf.MakeGenerator context if_false).ReturnTypes() - List.concat (Seq.ofList [true_ret_type; false_ret_type]) //TODO This should return closest common ancestor of these types - -type FunCallGenerator(context:Context,typeBuilder:TypeBuilder,fname:string,arguments:SExp list,gf:IGeneratorFactory) = - let args_seq = gf.MakeSequence context arguments - let func = context.functions.[new Symbol(fname)] <| args_seq.ReturnTypes() - interface IGenerator with - member this.Generate ilGen = - args_seq.Generate ilGen - ilGen.Emit(OpCodes.Call,func) - member this.ReturnTypes () = - [func.ReturnType] - -type DefunGenerator(context:Context,typeBuilder:TypeBuilder,fname:string,parameters:SExp list,body:SExp list,gf:IGeneratorFactory) = - do context.functions.[new Symbol(fname)] <- (fun arg_types -> - let methodGen = typeBuilder.DefineMethod(fname, MethodAttributes.Public ||| MethodAttributes.Static, typeof, (Array.ofList arg_types)) - let methodILGen = (methodGen.GetILGenerator()) - let fun_ctx = new Context(context) - for parm in parameters do - match parm with - | Atom(Symbol parm_name) -> - let parm_idx = (List.findIndex (fun (p) -> p = parm) parameters) - fun_ctx.locals.[new Symbol(parm_name)] <- Arg (parm_idx,arg_types.[parm_idx]) - | other -> failwithf "In function %A parameter definition:\nExpected: Atom(Symbol)\nGot: %A" fname parm - let methodFactory = gf.MakeGeneratorFactory typeBuilder methodGen - let bodyGen = methodFactory.MakeBody fun_ctx body - bodyGen.Generate methodILGen - methodILGen.Emit(OpCodes.Ret) - methodGen :> MethodInfo) - interface IGenerator with - member this.Generate ilGen = - () - member this.ReturnTypes() = - [typeof] - -type QuoteGenerator(context:Context,typeBuilder:TypeBuilder,quotedExp:SExp,gf:IGeneratorFactory) = - let generate_object (ilGen:ILGenerator) (o:obj) = - let generator = gf.MakeGenerator context (Atom (Object o)) - generator.Generate ilGen - let generate_symbol (ilGen:ILGenerator) (name:string) = - let cons = (typeof).GetConstructor [|typeof|] - ilGen.Emit(OpCodes.Ldstr,name) - ilGen.Emit(OpCodes.Newobj,cons) - let rec generate_list (ilGen:ILGenerator) (elements:SExp list) = - let generate_list_element e = - match e with - | List l -> generate_list ilGen l - | Atom (Object o) -> generate_object ilGen o - | Atom (Symbol s) -> generate_symbol ilGen s - | other -> failwithf "Error: Unexpected form in quoted expression: %A" other - let cons = (typeof).GetConstructor(Array.create 2 typeof) - List.rev elements |> List.head |> generate_list_element //last element - ilGen.Emit(OpCodes.Ldnull) //list terminator - ilGen.Emit(OpCodes.Newobj,cons) - List.rev elements |> List.tail |> List.iter (fun (e) -> - generate_list_element e - ilGen.Emit(OpCodes.Newobj,cons)) - interface IGenerator with - member this.Generate ilGen = - match quotedExp with - |List l -> generate_list ilGen l - |Atom (Object o) -> generate_object ilGen o - |Atom (Symbol s) -> generate_symbol ilGen s - member this.ReturnTypes () = - match quotedExp with - |List l -> [typeof] - |Atom (Object o) -> [typeof] - |Atom (Symbol s) -> [typeof] - -type NewObjGenerator(context : Context, typeBuilder : TypeBuilder, typeName : string, arguments : SExp list, gf : IGeneratorFactory) = - interface IGenerator with - member this.Generate ilGen = - let args_gen = gf.MakeSequence context arguments - let argTypes = args_gen.ReturnTypes() - let objType = - if typeName.StartsWith "System" then - Type.GetType typeName - else - context.types.[new Symbol(typeName)] - let arg_types = args_gen.Generate ilGen - ilGen.Emit(OpCodes.Newobj,objType.GetConstructor(Array.ofList argTypes)) - member this.ReturnTypes () = - if typeName.StartsWith "System" then - [Type.GetType typeName] - else - [context.types.[new Symbol(typeName)]] - -type TypeGenerator(context : Context, typeBuilder : TypeBuilder, typeName : string, parentTypeName: string, members : SExp list, gf : IGeneratorFactory) = - let newTypeBuilder = - if parentTypeName = "" then - Globals.ModuleBuilder.DefineType(typeName, TypeAttributes.Class ||| TypeAttributes.Public, typeof) - else - Globals.ModuleBuilder.DefineType(typeName, TypeAttributes.Class ||| TypeAttributes.Public, context.types.[new Symbol(parentTypeName)]) - let mutable fields : string list = [] - - let generate_field field_name = - let fieldBuilder = newTypeBuilder.DefineField(field_name,typeof,FieldAttributes.Public) - fields <- List.append fields [field_name] - let generate_method method_name method_parms method_body = - let method_gen = newTypeBuilder.DefineMethod(method_name,MethodAttributes.Public, - typeof, - Array.create (List.length method_parms) typeof) - let method_ctx = new Context(context) - for parm in method_parms do - match parm with - | Atom(Symbol parm_name) -> - let parm_idx = (List.findIndex (fun (p) -> p = parm) method_parms) - method_ctx.locals.[new Symbol(parm_name)] <- Arg (parm_idx,typeof) - | other -> failwithf "In method %A%A parameter definition:\nExpected: Atom(Symbol)\nGot: %A" typeName method_name parm - let newGeneratorFactory = gf.MakeGeneratorFactory newTypeBuilder method_gen - let body_gen = newGeneratorFactory.MakeBody method_ctx method_body - body_gen.Generate (method_gen.GetILGenerator()) - (method_gen.GetILGenerator()).Emit(OpCodes.Ret) - - interface IGenerator with - member this.Generate ilGen = - for m in members do - match m with - | List (Atom (Symbol "field") :: Atom (Symbol name) :: []) -> generate_field name - | List (Atom (Symbol "field") :: Atom (Symbol access) :: Atom (Symbol name) :: []) -> generate_field name - | List (Atom (Symbol "method") :: Atom (Symbol name) :: List parms :: body) -> generate_method name parms body - | List (Atom (Symbol "method") :: Atom (Symbol name) :: Atom (Symbol access) :: List parms :: body) -> generate_method name parms body - | other -> failwithf "In definition of type %A: \nUnknown member definition: %A" typeName other - member this.ReturnTypes () = - [typeof] +module Naggum.Compiler.FormGenerator + +open System +open System.Collections.Generic +open System.Reflection +open System.Reflection.Emit +open Naggum.Runtime +open Naggum.Compiler.Context +open Naggum.Compiler.IGenerator +open Naggum.Compiler.Reader + +type FormGenerator() = + interface IGenerator with + member this.Generate _ = failwith "Internal compiler error: unreified form generator invoked" + member this.ReturnTypes () = failwithf "Internal compiler error: inferring return type of unreified form" + +type ValueGenerator(context:Context,value:Value) = + inherit FormGenerator() + interface IGenerator with + member this.Generate _ = failwith "Internal compiler error: unreified value generator invoked" + member this.ReturnTypes () = failwithf "Internal compiler error: inferring return type of unreified value" + +type SymbolGenerator(context:Context,name:string) = + inherit ValueGenerator(context,Symbol name) + interface IGenerator with + member this.Generate ilGen = + try + let ctxval = context.locals.[new Symbol(name)] + match ctxval with + |Local (local, _) -> + ilGen.Emit(OpCodes.Ldloc,local) + |Arg (index,_) -> + ilGen.Emit(OpCodes.Ldarg,(int16 index)) + with + | :? KeyNotFoundException -> failwithf "Symbol %A not bound." name + member this.ReturnTypes () = + match context.locals.[new Symbol(name)] with + |Local (_,t) -> [t] + |Arg (_,t) -> [t] + + +type SequenceGenerator(context:Context,typeBuilder:TypeBuilder,seq:SExp list, gf:IGeneratorFactory) = + member private this.gen_seq (ilGen:ILGenerator,seq:SExp list) = + match seq with + | [] -> + () + | [last] -> + let gen = gf.MakeGenerator context last + gen.Generate ilGen + | sexp :: rest -> + let gen = gf.MakeGenerator context sexp + ignore (gen.Generate ilGen) + this.gen_seq (ilGen, rest) + interface IGenerator with + member this.Generate ilGen = this.gen_seq (ilGen,seq) + member this.ReturnTypes () = + List.map (fun (sexp) -> List.head ((gf.MakeGenerator context sexp).ReturnTypes())) seq + +type BodyGenerator(context : Context, + methodBuilder : MethodBuilder, + body : SExp list, + gf : IGeneratorFactory) = + let rec genBody (ilGen : ILGenerator) (body : SExp list) = + match body with + | [] -> + ilGen.Emit(OpCodes.Ldnull) + | [last] -> + let gen = gf.MakeGenerator context last + let stackType = List.head <| gen.ReturnTypes () + let returnType = methodBuilder.ReturnType + gen.Generate ilGen + match (stackType, returnType) with + | (s, r) when s = typeof && r = typeof -> () + | (s, r) when s = typeof && r <> typeof -> ilGen.Emit OpCodes.Ldnull + | (s, r) when s <> typeof && r = typeof -> ilGen.Emit OpCodes.Pop + | _ -> () + | sexp :: rest -> + let gen = gf.MakeGenerator context sexp + let val_type = gen.ReturnTypes() + gen.Generate ilGen + if List.head val_type <> typeof then + ilGen.Emit(OpCodes.Pop) + genBody ilGen rest + interface IGenerator with + member __.Generate ilGen = + genBody ilGen body + member this.ReturnTypes () = + match body with + |[] -> [typeof] + |somelist -> + let tail_type = (gf.MakeGenerator context (List.rev body |> List.head)).ReturnTypes() + if tail_type = [typeof] then + [typeof] + else tail_type + +type LetGenerator(context : Context, + typeBuilder : TypeBuilder, + methodBuilder : MethodBuilder, + bindings:SExp, + body : SExp list, + gf : IGeneratorFactory) = + interface IGenerator with + member this.Generate ilGen = + ilGen.BeginScope() + let scope_subctx = new Context (context) + match bindings with + | List list -> + for binding in list do + match binding with + | List [(Atom (Symbol name)); form] -> + let generator = gf.MakeGenerator scope_subctx form + let local_type = List.head (generator.ReturnTypes()) + let local = ilGen.DeclareLocal(local_type) + scope_subctx.locals.[new Symbol(name)] <- Local (local, local_type) + generator.Generate ilGen + ilGen.Emit (OpCodes.Stloc,local) + | other -> failwithf "In let bindings: Expected: (name (form))\nGot: %A\n" other + | other -> failwithf "In let form: expected: list of bindings\nGot: %A" other + let bodyGen = new BodyGenerator (scope_subctx, methodBuilder, body, gf) :> IGenerator + bodyGen.Generate ilGen + ilGen.EndScope() + member this.ReturnTypes () = + let type_subctx = new Context(context) + match bindings with + | List list -> + for binding in list do + match binding with + | List [(Atom (Symbol name)); form] -> + let generator = gf.MakeGenerator type_subctx form + type_subctx.locals.[new Symbol(name)] <- Local (null,generator.ReturnTypes() |> List.head) + | other -> failwithf "In let bindings: Expected: (name (form))\nGot: %A\n" other + | other -> failwithf "In let form: expected: list of bindings\nGot: %A" other + (gf.MakeBody type_subctx body).ReturnTypes() + +type ReducedIfGenerator(context:Context,typeBuilder:TypeBuilder,condition:SExp,if_true:SExp,gf:IGeneratorFactory) = + let returnTypes = (gf.MakeGenerator context if_true).ReturnTypes() + interface IGenerator with + member this.Generate ilGen = + let cond_gen = gf.MakeGenerator context condition + let if_true_gen = gf.MakeGenerator context if_true + let if_true_lbl = ilGen.DefineLabel() + let end_form = ilGen.DefineLabel() + cond_gen.Generate ilGen + ilGen.Emit (OpCodes.Brtrue, if_true_lbl) + + if List.head returnTypes <> typeof + then ilGen.Emit OpCodes.Ldnull + + ilGen.Emit (OpCodes.Br, end_form) + ilGen.MarkLabel if_true_lbl + if_true_gen.Generate ilGen + ilGen.MarkLabel end_form + member this.ReturnTypes () = + returnTypes + +type FullIfGenerator(context:Context,typeBuilder:TypeBuilder,condition:SExp,if_true:SExp,if_false:SExp,gf:IGeneratorFactory) = + interface IGenerator with + member this.Generate ilGen = + let cond_gen = gf.MakeGenerator context condition + let if_true_gen = gf.MakeGenerator context if_true + let if_false_gen = gf.MakeGenerator context if_false + let if_true_lbl = ilGen.DefineLabel() + let end_form = ilGen.DefineLabel() + ignore (cond_gen.Generate ilGen) + ilGen.Emit (OpCodes.Brtrue, if_true_lbl) + if_false_gen.Generate ilGen + ilGen.Emit (OpCodes.Br,end_form) + ilGen.MarkLabel if_true_lbl + if_true_gen.Generate ilGen + ilGen.MarkLabel end_form + member this.ReturnTypes () = + let true_ret_type = (gf.MakeGenerator context if_true).ReturnTypes() + let false_ret_type = (gf.MakeGenerator context if_false).ReturnTypes() + List.concat (Seq.ofList [true_ret_type; false_ret_type]) //TODO This should return closest common ancestor of these types + +type FunCallGenerator(context:Context,typeBuilder:TypeBuilder,fname:string,arguments:SExp list,gf:IGeneratorFactory) = + let args_seq = gf.MakeSequence context arguments + let func = context.functions.[new Symbol(fname)] <| args_seq.ReturnTypes() + interface IGenerator with + member this.Generate ilGen = + args_seq.Generate ilGen + ilGen.Emit(OpCodes.Call,func) + member this.ReturnTypes () = + [func.ReturnType] + +type DefunGenerator(context:Context,typeBuilder:TypeBuilder,fname:string,parameters:SExp list,body:SExp list,gf:IGeneratorFactory) = + do context.functions.[new Symbol(fname)] <- (fun arg_types -> + let methodGen = typeBuilder.DefineMethod(fname, MethodAttributes.Public ||| MethodAttributes.Static, typeof, (Array.ofList arg_types)) + let methodILGen = (methodGen.GetILGenerator()) + let fun_ctx = new Context(context) + for parm in parameters do + match parm with + | Atom(Symbol parm_name) -> + let parm_idx = (List.findIndex (fun (p) -> p = parm) parameters) + fun_ctx.locals.[new Symbol(parm_name)] <- Arg (parm_idx,arg_types.[parm_idx]) + | other -> failwithf "In function %A parameter definition:\nExpected: Atom(Symbol)\nGot: %A" fname parm + let methodFactory = gf.MakeGeneratorFactory typeBuilder methodGen + let bodyGen = methodFactory.MakeBody fun_ctx body + bodyGen.Generate methodILGen + methodILGen.Emit(OpCodes.Ret) + methodGen :> MethodInfo) + interface IGenerator with + member this.Generate ilGen = + () + member this.ReturnTypes() = + [typeof] + +type QuoteGenerator(context:Context,typeBuilder:TypeBuilder,quotedExp:SExp,gf:IGeneratorFactory) = + let generate_object (ilGen:ILGenerator) (o:obj) = + let generator = gf.MakeGenerator context (Atom (Object o)) + generator.Generate ilGen + let generate_symbol (ilGen:ILGenerator) (name:string) = + let cons = (typeof).GetConstructor [|typeof|] + ilGen.Emit(OpCodes.Ldstr,name) + ilGen.Emit(OpCodes.Newobj,cons) + let rec generate_list (ilGen:ILGenerator) (elements:SExp list) = + let generate_list_element e = + match e with + | List l -> generate_list ilGen l + | Atom (Object o) -> generate_object ilGen o + | Atom (Symbol s) -> generate_symbol ilGen s + | other -> failwithf "Error: Unexpected form in quoted expression: %A" other + let cons = (typeof).GetConstructor(Array.create 2 typeof) + List.rev elements |> List.head |> generate_list_element //last element + ilGen.Emit(OpCodes.Ldnull) //list terminator + ilGen.Emit(OpCodes.Newobj,cons) + List.rev elements |> List.tail |> List.iter (fun (e) -> + generate_list_element e + ilGen.Emit(OpCodes.Newobj,cons)) + interface IGenerator with + member this.Generate ilGen = + match quotedExp with + |List l -> generate_list ilGen l + |Atom (Object o) -> generate_object ilGen o + |Atom (Symbol s) -> generate_symbol ilGen s + member this.ReturnTypes () = + match quotedExp with + |List l -> [typeof] + |Atom (Object o) -> [typeof] + |Atom (Symbol s) -> [typeof] + +type NewObjGenerator(context : Context, typeBuilder : TypeBuilder, typeName : string, arguments : SExp list, gf : IGeneratorFactory) = + interface IGenerator with + member this.Generate ilGen = + let args_gen = gf.MakeSequence context arguments + let argTypes = args_gen.ReturnTypes() + let objType = + if typeName.StartsWith "System" then + Type.GetType typeName + else + context.types.[new Symbol(typeName)] + let arg_types = args_gen.Generate ilGen + ilGen.Emit(OpCodes.Newobj,objType.GetConstructor(Array.ofList argTypes)) + member this.ReturnTypes () = + if typeName.StartsWith "System" then + [Type.GetType typeName] + else + [context.types.[new Symbol(typeName)]] + +type TypeGenerator(context : Context, typeBuilder : TypeBuilder, typeName : string, parentTypeName: string, members : SExp list, gf : IGeneratorFactory) = + let newTypeBuilder = + if parentTypeName = "" then + Globals.ModuleBuilder.DefineType(typeName, TypeAttributes.Class ||| TypeAttributes.Public, typeof) + else + Globals.ModuleBuilder.DefineType(typeName, TypeAttributes.Class ||| TypeAttributes.Public, context.types.[new Symbol(parentTypeName)]) + let mutable fields : string list = [] + + let generate_field field_name = + let fieldBuilder = newTypeBuilder.DefineField(field_name,typeof,FieldAttributes.Public) + fields <- List.append fields [field_name] + let generate_method method_name method_parms method_body = + let method_gen = newTypeBuilder.DefineMethod(method_name,MethodAttributes.Public, + typeof, + Array.create (List.length method_parms) typeof) + let method_ctx = new Context(context) + for parm in method_parms do + match parm with + | Atom(Symbol parm_name) -> + let parm_idx = (List.findIndex (fun (p) -> p = parm) method_parms) + method_ctx.locals.[new Symbol(parm_name)] <- Arg (parm_idx,typeof) + | other -> failwithf "In method %A%A parameter definition:\nExpected: Atom(Symbol)\nGot: %A" typeName method_name parm + let newGeneratorFactory = gf.MakeGeneratorFactory newTypeBuilder method_gen + let body_gen = newGeneratorFactory.MakeBody method_ctx method_body + body_gen.Generate (method_gen.GetILGenerator()) + (method_gen.GetILGenerator()).Emit(OpCodes.Ret) + + interface IGenerator with + member this.Generate ilGen = + for m in members do + match m with + | List (Atom (Symbol "field") :: Atom (Symbol name) :: []) -> generate_field name + | List (Atom (Symbol "field") :: Atom (Symbol access) :: Atom (Symbol name) :: []) -> generate_field name + | List (Atom (Symbol "method") :: Atom (Symbol name) :: List parms :: body) -> generate_method name parms body + | List (Atom (Symbol "method") :: Atom (Symbol name) :: Atom (Symbol access) :: List parms :: body) -> generate_method name parms body + | other -> failwithf "In definition of type %A: \nUnknown member definition: %A" typeName other + member this.ReturnTypes () = + [typeof] diff --git a/ngc/Generator.fs b/ngc/Generator.fs index b430cb3..99e582c 100644 --- a/ngc/Generator.fs +++ b/ngc/Generator.fs @@ -1,65 +1,65 @@ -module Naggum.Compiler.Generator - -open System -open System.IO -open System.Reflection -open System.Reflection.Emit - -open Naggum.Compiler.IGenerator -open Naggum.Compiler.GeneratorFactory -open Naggum.Compiler.Reader - -let private prologue (ilGen : ILGenerator) = - ilGen.BeginScope() - -let private epilogue context (ilGen : ILGenerator) = - ilGen.Emit OpCodes.Ret - ilGen.EndScope() - -let compileMethod context (generatorFactory : IGeneratorFactory) body (methodBuilder : MethodBuilder) fileName = - let ilGenerator = methodBuilder.GetILGenerator() - - prologue ilGenerator - try - let gen = generatorFactory.MakeBody context body - gen.Generate ilGenerator - with - | ex -> printfn "File: %A\nForm: %A\nError: %A" fileName sexp ex.Source - - epilogue context ilGenerator - -let compile (source : Stream) (assemblyName : string) (filePath : string) (asmRefs:string list): unit = - let assemblyName = AssemblyName assemblyName - let path = Path.GetDirectoryName filePath - let assemblyPath = if path = "" then null else path - let fileName = Path.GetFileName filePath - let appDomain = AppDomain.CurrentDomain - - let assemblyBuilder = appDomain.DefineDynamicAssembly (assemblyName, AssemblyBuilderAccess.Save, assemblyPath) - Globals.ModuleBuilder <- assemblyBuilder.DefineDynamicModule(assemblyBuilder.GetName().Name, fileName) - let typeBuilder = Globals.ModuleBuilder.DefineType("Program", TypeAttributes.Public ||| TypeAttributes.Class ||| TypeAttributes.BeforeFieldInit) - let methodBuilder = typeBuilder.DefineMethod ("Main", - MethodAttributes.Public ||| MethodAttributes.Static, - typeof, - [| |]) - - let gf = new GeneratorFactory(typeBuilder, methodBuilder) :> IGeneratorFactory - assemblyBuilder.SetEntryPoint methodBuilder - - let context = Context.create () - - //loading language runtime - let rta = Assembly.LoadFrom("Naggum.Runtime.dll") - context.loadAssembly rta - - // Load .NET runtime and all referenced assemblies: - context.loadAssembly <| Assembly.Load "mscorlib" - List.iter context.loadAssembly (List.map Assembly.LoadFrom asmRefs) - - let body = Reader.parse fileName source - compileMethod context gf body methodBuilder fileName - - typeBuilder.CreateType() - |> ignore - - assemblyBuilder.Save fileName +module Naggum.Compiler.Generator + +open System +open System.IO +open System.Reflection +open System.Reflection.Emit + +open Naggum.Compiler.IGenerator +open Naggum.Compiler.GeneratorFactory +open Naggum.Compiler.Reader + +let private prologue (ilGen : ILGenerator) = + ilGen.BeginScope() + +let private epilogue context (ilGen : ILGenerator) = + ilGen.Emit OpCodes.Ret + ilGen.EndScope() + +let compileMethod context (generatorFactory : IGeneratorFactory) body (methodBuilder : MethodBuilder) fileName = + let ilGenerator = methodBuilder.GetILGenerator() + + prologue ilGenerator + try + let gen = generatorFactory.MakeBody context body + gen.Generate ilGenerator + with + | ex -> printfn "File: %A\nForm: %A\nError: %A" fileName sexp ex.Source + + epilogue context ilGenerator + +let compile (source : Stream) (assemblyName : string) (filePath : string) (asmRefs:string list): unit = + let assemblyName = AssemblyName assemblyName + let path = Path.GetDirectoryName filePath + let assemblyPath = if path = "" then null else path + let fileName = Path.GetFileName filePath + let appDomain = AppDomain.CurrentDomain + + let assemblyBuilder = appDomain.DefineDynamicAssembly (assemblyName, AssemblyBuilderAccess.Save, assemblyPath) + Globals.ModuleBuilder <- assemblyBuilder.DefineDynamicModule(assemblyBuilder.GetName().Name, fileName) + let typeBuilder = Globals.ModuleBuilder.DefineType("Program", TypeAttributes.Public ||| TypeAttributes.Class ||| TypeAttributes.BeforeFieldInit) + let methodBuilder = typeBuilder.DefineMethod ("Main", + MethodAttributes.Public ||| MethodAttributes.Static, + typeof, + [| |]) + + let gf = new GeneratorFactory(typeBuilder, methodBuilder) :> IGeneratorFactory + assemblyBuilder.SetEntryPoint methodBuilder + + let context = Context.create () + + //loading language runtime + let rta = Assembly.LoadFrom("Naggum.Runtime.dll") + context.loadAssembly rta + + // Load .NET runtime and all referenced assemblies: + context.loadAssembly <| Assembly.Load "mscorlib" + List.iter context.loadAssembly (List.map Assembly.LoadFrom asmRefs) + + let body = Reader.parse fileName source + compileMethod context gf body methodBuilder fileName + + typeBuilder.CreateType() + |> ignore + + assemblyBuilder.Save fileName diff --git a/ngc/Globals.fs b/ngc/Globals.fs index f6c5662..0fc9c65 100644 --- a/ngc/Globals.fs +++ b/ngc/Globals.fs @@ -1,5 +1,5 @@ -module Naggum.Compiler.Globals - -open System.Reflection.Emit - +module Naggum.Compiler.Globals + +open System.Reflection.Emit + let mutable ModuleBuilder:ModuleBuilder = null \ No newline at end of file diff --git a/ngc/MathGenerator.fs b/ngc/MathGenerator.fs index ccc6d85..26d82e0 100644 --- a/ngc/MathGenerator.fs +++ b/ngc/MathGenerator.fs @@ -1,48 +1,48 @@ -module Naggum.Compiler.MathGenerator - -open System -open System.Reflection.Emit - -open Naggum.Compiler.Reader -open Naggum.Compiler.Context -open Naggum.Compiler.IGenerator - -//TODO: Make this useful; i.e. determine eldest type in a numeric tower and convert all junior types to eldest -let tower = dict [(typeof, 1); (typeof, 2); (typeof, 3); (typeof, 4); (typeof,5)] - -let maxType types = - try - let maxOrder = List.maxBy (fun (t) -> tower.[t]) types - (Seq.find (fun (KeyValue(o,_)) -> o = maxOrder) tower).Key - with - | :? System.Collections.Generic.KeyNotFoundException -> failwithf "Some types of %A are not suitable in an arithmetic expression." types - -type ArithmeticGenerator(context:Context,typeBuilder:TypeBuilder,args:SExp list, operation:OpCode, gf:IGeneratorFactory) = - interface IGenerator with - member this.Generate ilGen = - //making this just for the sake of return types - let max_type = (gf.MakeSequence context args).ReturnTypes() |> maxType - //loading first arg manually so it won't be succeeded by operation opcode - let arg_gen = gf.MakeGenerator context (List.head args) - let arg_type = arg_gen.ReturnTypes() |> List.head - arg_gen.Generate ilGen - if not (arg_type = max_type) then - ilGen.Emit(OpCodes.Newobj, max_type.GetConstructor [|arg_type|]) - for arg in List.tail args do - let arg_gen = gf.MakeGenerator context arg - let arg_type = arg_gen.ReturnTypes() |> List.head - arg_gen.Generate ilGen - ilGen.Emit(operation) - member this.ReturnTypes () = - [List.map (fun (sexp) -> (gf.MakeGenerator context sexp).ReturnTypes() |> List.head) args |> maxType] - -type SimpleLogicGenerator(context:Context,typeBuilder:TypeBuilder,arg_a:SExp, arg_b:SExp, operation:OpCode, gf:IGeneratorFactory) = - interface IGenerator with - member this.Generate ilGen = - let a_gen = gf.MakeGenerator context arg_a - let b_gen = gf.MakeGenerator context arg_b - a_gen.Generate ilGen |> ignore - b_gen.Generate ilGen |> ignore - ilGen.Emit(operation) - member this.ReturnTypes () = +module Naggum.Compiler.MathGenerator + +open System +open System.Reflection.Emit + +open Naggum.Compiler.Reader +open Naggum.Compiler.Context +open Naggum.Compiler.IGenerator + +//TODO: Make this useful; i.e. determine eldest type in a numeric tower and convert all junior types to eldest +let tower = dict [(typeof, 1); (typeof, 2); (typeof, 3); (typeof, 4); (typeof,5)] + +let maxType types = + try + let maxOrder = List.maxBy (fun (t) -> tower.[t]) types + (Seq.find (fun (KeyValue(o,_)) -> o = maxOrder) tower).Key + with + | :? System.Collections.Generic.KeyNotFoundException -> failwithf "Some types of %A are not suitable in an arithmetic expression." types + +type ArithmeticGenerator(context:Context,typeBuilder:TypeBuilder,args:SExp list, operation:OpCode, gf:IGeneratorFactory) = + interface IGenerator with + member this.Generate ilGen = + //making this just for the sake of return types + let max_type = (gf.MakeSequence context args).ReturnTypes() |> maxType + //loading first arg manually so it won't be succeeded by operation opcode + let arg_gen = gf.MakeGenerator context (List.head args) + let arg_type = arg_gen.ReturnTypes() |> List.head + arg_gen.Generate ilGen + if not (arg_type = max_type) then + ilGen.Emit(OpCodes.Newobj, max_type.GetConstructor [|arg_type|]) + for arg in List.tail args do + let arg_gen = gf.MakeGenerator context arg + let arg_type = arg_gen.ReturnTypes() |> List.head + arg_gen.Generate ilGen + ilGen.Emit(operation) + member this.ReturnTypes () = + [List.map (fun (sexp) -> (gf.MakeGenerator context sexp).ReturnTypes() |> List.head) args |> maxType] + +type SimpleLogicGenerator(context:Context,typeBuilder:TypeBuilder,arg_a:SExp, arg_b:SExp, operation:OpCode, gf:IGeneratorFactory) = + interface IGenerator with + member this.Generate ilGen = + let a_gen = gf.MakeGenerator context arg_a + let b_gen = gf.MakeGenerator context arg_b + a_gen.Generate ilGen |> ignore + b_gen.Generate ilGen |> ignore + ilGen.Emit(operation) + member this.ReturnTypes () = [typeof] \ No newline at end of file diff --git a/ngc/MaybeMonad.fs b/ngc/MaybeMonad.fs index a88be02..afcddc5 100644 --- a/ngc/MaybeMonad.fs +++ b/ngc/MaybeMonad.fs @@ -1,11 +1,11 @@ -module Naggum.Util.MaybeMonad - -type MaybeMonad() = - member x.Bind(m, f) = - match m with - | Some v -> f v - | None -> None - - member x.Return v = Some v - -let maybe = new MaybeMonad() +module Naggum.Util.MaybeMonad + +type MaybeMonad() = + member x.Bind(m, f) = + match m with + | Some v -> f v + | None -> None + + member x.Return v = Some v + +let maybe = new MaybeMonad() diff --git a/ngc/Program.fs b/ngc/Program.fs index 6913fb8..e21dd47 100644 --- a/ngc/Program.fs +++ b/ngc/Program.fs @@ -1,19 +1,19 @@ -module Naggum.Compiler.Program - -open System -open System.IO -open Naggum.Compiler.Generator - -let args = List.ofArray (Environment.GetCommandLineArgs()) -let mutable sources = [] -let mutable asmRefs = [] -for arg in (List.tail args) do - if arg.StartsWith "/r:" then - asmRefs <- arg.Replace("/r:","") :: asmRefs - else - sources <- arg :: sources -for fileName in sources do - let source = File.Open (fileName,FileMode.Open) :> Stream - let assemblyName = Path.GetFileNameWithoutExtension fileName - Generator.compile source assemblyName (assemblyName + ".exe") asmRefs - source.Close() +module Naggum.Compiler.Program + +open System +open System.IO +open Naggum.Compiler.Generator + +let args = List.ofArray (Environment.GetCommandLineArgs()) +let mutable sources = [] +let mutable asmRefs = [] +for arg in (List.tail args) do + if arg.StartsWith "/r:" then + asmRefs <- arg.Replace("/r:","") :: asmRefs + else + sources <- arg :: sources +for fileName in sources do + let source = File.Open (fileName,FileMode.Open) :> Stream + let assemblyName = Path.GetFileNameWithoutExtension fileName + Generator.compile source assemblyName (assemblyName + ".exe") asmRefs + source.Close() diff --git a/ngc/Reader.fs b/ngc/Reader.fs index 29140ec..a958180 100644 --- a/ngc/Reader.fs +++ b/ngc/Reader.fs @@ -1,70 +1,70 @@ -module Naggum.Compiler.Reader - -open System.IO -open FParsec.CharParsers - -open System -open System.IO -open FParsec - -type Value = - |Object of obj - |Symbol of string - -type SExp = - | Atom of Value - | List of SExp list - -let comment = (skipChar ';') .>> (skipRestOfLine true) -let skipSpaceAndComments = skipMany (spaces1 <|> comment) -let commented parser = skipSpaceAndComments >>. parser .>> skipSpaceAndComments -let list,listRef = createParserForwardedToRef() - -let numberOptions = - NumberLiteralOptions.AllowMinusSign - ||| NumberLiteralOptions.AllowExponent - ||| NumberLiteralOptions.AllowHexadecimal - ||| NumberLiteralOptions.AllowFraction - ||| NumberLiteralOptions.AllowSuffix -let pnumber : Parser = - let pliteral = numberLiteral numberOptions "number" - fun stream -> - let reply = pliteral stream - if reply.Status = Ok then - let result : NumberLiteral = reply.Result - if result.IsInteger then - if result.SuffixLength = 1 && result.SuffixChar1 = 'L' then - Reply((int64 result.String) :> obj |> Object) - else - if not (result.SuffixLength = 1) then - Reply((int32 result.String) :> obj |> Object) - else - Reply (ReplyStatus.Error, messageError <| sprintf "Unknown suffix: %A" result.SuffixChar1) - else - if result.SuffixLength = 1 && result.SuffixChar1 = 'f' then - Reply((float result.String) :> obj |> Object) - else - if not (result.SuffixLength = 1) then - Reply((single result.String) :> obj |> Object) - else - Reply (ReplyStatus.Error, messageError <| sprintf "Unknown suffix: %A" result.SuffixChar1) - else - Reply(reply.Status,reply.Error) -let string = - let normalChar = satisfy (fun c -> c <> '\"') - between (pstring "\"")(pstring "\"") (manyChars normalChar) |>> (fun (str) -> str :> obj) |>> Object -let symChars = (anyOf "+-*/=<>!?.") //chars that are valid in the symbol name -let symbol = (many1Chars (letter <|> digit <|> symChars)) |>> Symbol - -let atom = (pnumber <|> string <|> symbol) |>> Atom - -let listElement = choice [atom;list] -let sexp = commented (pchar '(') >>. many (commented listElement) .>> commented (pchar ')') |>> List -let parser = many1 (choice [atom;sexp]) -do listRef := sexp - -let parse (sourceName:string) (source : Stream) = - let form = runParserOnStream parser () sourceName source Text.Encoding.UTF8 - match form with - | Success(result, _, _) -> result - | Failure(errorMsg, _, _) -> failwithf "Failure: %s" errorMsg +module Naggum.Compiler.Reader + +open System.IO +open FParsec.CharParsers + +open System +open System.IO +open FParsec + +type Value = + |Object of obj + |Symbol of string + +type SExp = + | Atom of Value + | List of SExp list + +let comment = (skipChar ';') .>> (skipRestOfLine true) +let skipSpaceAndComments = skipMany (spaces1 <|> comment) +let commented parser = skipSpaceAndComments >>. parser .>> skipSpaceAndComments +let list,listRef = createParserForwardedToRef() + +let numberOptions = + NumberLiteralOptions.AllowMinusSign + ||| NumberLiteralOptions.AllowExponent + ||| NumberLiteralOptions.AllowHexadecimal + ||| NumberLiteralOptions.AllowFraction + ||| NumberLiteralOptions.AllowSuffix +let pnumber : Parser = + let pliteral = numberLiteral numberOptions "number" + fun stream -> + let reply = pliteral stream + if reply.Status = Ok then + let result : NumberLiteral = reply.Result + if result.IsInteger then + if result.SuffixLength = 1 && result.SuffixChar1 = 'L' then + Reply((int64 result.String) :> obj |> Object) + else + if not (result.SuffixLength = 1) then + Reply((int32 result.String) :> obj |> Object) + else + Reply (ReplyStatus.Error, messageError <| sprintf "Unknown suffix: %A" result.SuffixChar1) + else + if result.SuffixLength = 1 && result.SuffixChar1 = 'f' then + Reply((float result.String) :> obj |> Object) + else + if not (result.SuffixLength = 1) then + Reply((single result.String) :> obj |> Object) + else + Reply (ReplyStatus.Error, messageError <| sprintf "Unknown suffix: %A" result.SuffixChar1) + else + Reply(reply.Status,reply.Error) +let string = + let normalChar = satisfy (fun c -> c <> '\"') + between (pstring "\"")(pstring "\"") (manyChars normalChar) |>> (fun (str) -> str :> obj) |>> Object +let symChars = (anyOf "+-*/=<>!?.") //chars that are valid in the symbol name +let symbol = (many1Chars (letter <|> digit <|> symChars)) |>> Symbol + +let atom = (pnumber <|> string <|> symbol) |>> Atom + +let listElement = choice [atom;list] +let sexp = commented (pchar '(') >>. many (commented listElement) .>> commented (pchar ')') |>> List +let parser = many1 (choice [atom;sexp]) +do listRef := sexp + +let parse (sourceName:string) (source : Stream) = + let form = runParserOnStream parser () sourceName source Text.Encoding.UTF8 + match form with + | Success(result, _, _) -> result + | Failure(errorMsg, _, _) -> failwithf "Failure: %s" errorMsg diff --git a/ngc/ngc.fsproj b/ngc/ngc.fsproj index cdf873a..26078e8 100644 --- a/ngc/ngc.fsproj +++ b/ngc/ngc.fsproj @@ -1,104 +1,104 @@ - - - - Debug - x86 - 8.0.30703 - 2.0 - {a4269c5e-e4ac-44bf-a06e-1b45248910ad} - Exe - ngc - ngc - v4.6.1 - - - ngc - - - 4.4.0.0 - 11 - - - true - full - false - false - ..\bin\ - DEBUG;TRACE - 3 - AnyCPU - bin\Debug\ngc.XML - ..\tests\test.naggum - - - pdbonly - true - true - ..\bin\ - TRACE - 3 - AnyCPU - bin\Release\ngc.XML - - - - - $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets - - - - - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets - - - - - - - - - - - - - - - - - - - - Always - - - - - - ..\packages\FParsec.1.0.2\lib\net40-client\FParsec.dll - True - - - ..\packages\FParsec.1.0.2\lib\net40-client\FParsecCS.dll - True - - - True - - - - - - - Naggum.Runtime - {402b5e79-e063-4833-ae4b-2986aeec1d75} - True - - - + + + + Debug + x86 + 8.0.30703 + 2.0 + {a4269c5e-e4ac-44bf-a06e-1b45248910ad} + Exe + ngc + ngc + v4.6.1 + + + ngc + + + 4.4.0.0 + 11 + + + true + full + false + false + ..\bin\ + DEBUG;TRACE + 3 + AnyCPU + bin\Debug\ngc.XML + ..\tests\test.naggum + + + pdbonly + true + true + ..\bin\ + TRACE + 3 + AnyCPU + bin\Release\ngc.XML + + + + + $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets + + + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets + + + + + + + + + + + + + + + + + + + + Always + + + + + + ..\packages\FParsec.1.0.2\lib\net40-client\FParsec.dll + True + + + ..\packages\FParsec.1.0.2\lib\net40-client\FParsecCS.dll + True + + + True + + + + + + + Naggum.Runtime + {402b5e79-e063-4833-ae4b-2986aeec1d75} + True + + + \ No newline at end of file