diff options
| author | krasimir <krasimir@chalmers.se> | 2017-05-31 13:48:36 +0000 |
|---|---|---|
| committer | krasimir <krasimir@chalmers.se> | 2017-05-31 13:48:36 +0000 |
| commit | e1cec06f7483ea913885a7918728a1c3f8ece650 (patch) | |
| tree | a79d46b37747a60d285090e22572ea4f3810814d /src/runtime | |
| parent | 2a8d2806e4612d320de0155d8cdbbd68cd1d1995 (diff) | |
.NET binding to GF by Bjørnar Luteberget
Diffstat (limited to 'src/runtime')
| -rw-r--r-- | src/runtime/dotNet/Bracket.cs | 120 | ||||
| -rw-r--r-- | src/runtime/dotNet/Concr.cs | 173 | ||||
| -rw-r--r-- | src/runtime/dotNet/Exceptions.cs | 46 | ||||
| -rw-r--r-- | src/runtime/dotNet/Expr.cs | 133 | ||||
| -rw-r--r-- | src/runtime/dotNet/Expr/Abstraction.cs | 15 | ||||
| -rw-r--r-- | src/runtime/dotNet/Expr/Application.cs | 57 | ||||
| -rw-r--r-- | src/runtime/dotNet/Expr/Function.cs | 18 | ||||
| -rw-r--r-- | src/runtime/dotNet/Expr/Literal.cs | 127 | ||||
| -rw-r--r-- | src/runtime/dotNet/Expr/MetaVariable.cs | 34 | ||||
| -rw-r--r-- | src/runtime/dotNet/Native.cs | 306 | ||||
| -rw-r--r-- | src/runtime/dotNet/NativeGU.cs | 127 | ||||
| -rw-r--r-- | src/runtime/dotNet/PGF.cs | 157 | ||||
| -rw-r--r-- | src/runtime/dotNet/PGFSharp.csproj | 68 | ||||
| -rw-r--r-- | src/runtime/dotNet/Properties/AssemblyInfo.cs | 36 | ||||
| -rw-r--r-- | src/runtime/dotNet/Type.cs | 92 |
15 files changed, 1509 insertions, 0 deletions
diff --git a/src/runtime/dotNet/Bracket.cs b/src/runtime/dotNet/Bracket.cs new file mode 100644 index 000000000..fa9c77d74 --- /dev/null +++ b/src/runtime/dotNet/Bracket.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PGFSharp +{ + // Brackets should only be constructed from the Concrete class. + // These classes just store the data, they do not own or use + // unmanaged memory (except in the builder class). + + public interface IBracketChild { + bool IsString {get;} + string AsStringChild {get;} + Bracket AsBracketChild {get;} + } + + + public class Bracket : IBracketChild + { + public class StringChildBracket : IBracketChild { + + string str; + internal StringChildBracket(string str) { + this.str = str; + } + + public bool IsString => true; + public string AsStringChild => str; + public Bracket AsBracketChild { + get { + throw new NotImplementedException (); + } + } + + public override string ToString () => AsStringChild; + } + + internal class BracketBuilder { + internal Native.PgfLinFuncs LinFuncs { get; private set; } + + private Stack<Bracket> stack = new Stack<Bracket> (); + private Bracket final = null; + internal BracketBuilder() { + LinFuncs = new Native.PgfLinFuncs { + symbol_token = SymbolToken, + begin_prase = BeginPhrase, + end_phrase = EndPhrase, + symbol_ne = null, + symbol_bind = null, + symbol_capit = null + }; + } + + // TODO: the Python wrapper discards begin/end phrase pairs + // which don't have any tokens. Is this correct and/or necessary? + private void SymbolToken(IntPtr self, IntPtr token) { + var str = Native.NativeString.StringFromNativeUtf8 (token); + stack.Peek ().AddChild (new StringChildBracket (str)); + } + + private void BeginPhrase(IntPtr self, IntPtr cat, int fid, int lindex, IntPtr fun) { + stack.Push (new Bracket ()); + } + + private void EndPhrase(IntPtr self, IntPtr cat, int fid, int lindex, IntPtr fun) { + var b = stack.Pop (); + + b.CatName = Native.NativeString.StringFromNativeUtf8 (cat); + b.FunName = Native.NativeString.StringFromNativeUtf8 (fun); + b.FId = fid; + b.LIndex = lindex; + + if (stack.Count == 0) + final = b; + else + stack.Peek ().AddChild (b); + } + + public Bracket Build() { + return final; + } + } + + private List<IBracketChild> _children = new List<IBracketChild> (); + private Bracket() { + } + + private void AddChild(IBracketChild c) { + _children.Add(c); + } + + public bool IsString => false; + public Bracket AsBracketChild => this; + public string AsStringChild { + get { + throw new NotImplementedException (); + } + } + + public IEnumerable<IBracketChild> Children { get { return _children; } } + + public string CatName { get; private set; } + public string FunName { get; private set; } + public int FId { get; private set; } + public int LIndex { get; private set; } + + public override string ToString () + { + return "(" + CatName + ":" + FId + " " + String.Join (" ", Children) + ")"; + } + + public string ToBracketsString => "{" + String.Join(" ", + Children.Select(c => (c is Bracket) ? ((Bracket)c).ToBracketsString : c.ToString() ) + ) + "}"; + } + + +} diff --git a/src/runtime/dotNet/Concr.cs b/src/runtime/dotNet/Concr.cs new file mode 100644 index 000000000..cbb4c6d51 --- /dev/null +++ b/src/runtime/dotNet/Concr.cs @@ -0,0 +1,173 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Runtime.InteropServices; + +namespace PGFSharp +{ + /// <summary> + /// Concrete grammar. All concrete grammars are available from the (Abstract) <see cref="Grammar"/> class. + /// </summary> + public class Concr + { + internal IntPtr Ptr { get; private set; } + + /// <summary> + /// Abstract grammar for this language. + /// </summary> + public PGF PGF { get; private set; } + + private Concr() { } + + internal static Concr FromPtr(PGF g, IntPtr ptr) + { + var concr = new Concr(); + concr.PGF = g; + concr.Ptr = ptr; + return concr; + } + + /// <summary> + /// Name of the grammar. + /// </summary> + public string Name => Native.NativeString.StringFromNativeUtf8(Native.pgf_concrete_name(Ptr)); + public override string ToString() => $"Concrete:{Name} of {PGF.Name}"; + + /// <summary> + /// Parse given input string in the concrete grammar. + /// </summary> + /// <param name="str">Input string to be parsed.</param> + /// <param name="cat">Category (Type) to parse.</param> + /// <param name="heuristics">Heuristic (see the GF C runtime docs).</param> + /// <param name="Callback1">Callback function.</param> + /// <param name="Callback2">Callback function.</param> + /// <returns>Enumerates pairs of (abstract grammar) expressions and corresponding probability.</returns> + public IEnumerable<Tuple<Expr, float>> Parse(string str, Type cat = null, double? heuristics = null, + Action Callback1 = null, Action Callback2 = null) + { + var parse_pool = new NativeGU.NativeMemoryPool(); + var exn = new NativeGU.NativeExceptionContext(parse_pool); + cat = cat ?? PGF.StartCat; + + using (var nativeStr = new Native.NativeString(str)) + { + var result_pool = new NativeGU.NativeMemoryPool(); + var callbackMap = Native.pgf_new_callbacks_map(this.Ptr, parse_pool.Ptr); + + var iterator = Native.pgf_parse_with_heuristics(this.Ptr, cat.Ptr, + nativeStr.Ptr, heuristics ?? -1, callbackMap, + exn.Ptr, parse_pool.Ptr, result_pool.Ptr); + + if (iterator == IntPtr.Zero || exn.IsRaised) + { + throw new ParseError(); + } + else + { + foreach (var ptr in NativeGU.IteratorToIEnumerable(iterator, parse_pool.Ptr)) + { + var exprProb = (Native.PgfExprProb)Marshal.PtrToStructure(ptr, typeof(Native.PgfExprProb)); + yield return Tuple.Create(Expr.FromPtr(exprProb.expr, result_pool), + exprProb.prob); + } + } + } + } + + /// <summary> + /// Linearize expression, i.e. produce a string in the concrete grammar from an expression in the abstract grammar. + /// </summary> + /// <param name="e"></param> + /// <returns></returns> + public string Linearize(Expr e) + { + var tmp_pool = new NativeGU.NativeMemoryPool(); + var exn = new NativeGU.NativeExceptionContext(tmp_pool); + + var buf = NativeGU.gu_new_string_buf(tmp_pool.Ptr); + var out_ = NativeGU.gu_string_buf_out(buf); + + Native.pgf_linearize(Ptr, e.Ptr, out_, exn.Ptr); + if (exn.IsRaised) + { + throw new PGFError(); + } + else + { + var cstr = NativeGU.gu_string_buf_freeze(buf, tmp_pool.Ptr); + return Native.NativeString.StringFromNativeUtf8(cstr); + } + } + + /// <summary> + /// Get all possible linearization for an expression (see <see cref="Linearize(Expression)"/>). + /// </summary> + /// <param name="e"></param> + /// <returns></returns> + public IEnumerable<string> LinearizeAll(Expr e) + { + var tmp_pool = new NativeGU.NativeMemoryPool(); + var exn = new NativeGU.NativeExceptionContext(tmp_pool); + + var cts = Native.pgf_lzr_concretize(Ptr, e.Ptr, exn.Ptr, tmp_pool.Ptr); + if (exn.IsRaised || cts == IntPtr.Zero) throw new PGFError("Could not linearize the abstract tree."); + + return NativeGU.IteratorToIEnumerable(cts, tmp_pool.Ptr).Select(LinearizeCnc); + } + + private string LinearizeCnc(IntPtr cnc) + { + var tmp_pool = new NativeGU.NativeMemoryPool(); + var exn = new NativeGU.NativeExceptionContext(tmp_pool); + + var sbuf = NativeGU.gu_new_string_buf(tmp_pool.Ptr); + var out_ = NativeGU.gu_string_buf_out(sbuf); + + var wrapped = Native.pgf_lzr_wrap_linref(cnc, tmp_pool.Ptr); + Native.pgf_lzr_linearize_simple(Ptr, wrapped, 0, out_, exn.Ptr, tmp_pool.Ptr); + + if (exn.IsRaised) throw new PGFError("Could not linearize abstract tree."); + + var cstr = NativeGU.gu_string_buf_freeze(sbuf, tmp_pool.Ptr); + return Native.NativeString.StringFromNativeUtf8(cstr); + } + + /// <summary> + /// Get the bracketed (structured) linearization of an expression. + /// </summary> + /// <param name="e"></param> + /// <returns></returns> + public Bracket BracketedLinearize(Expr e) + { + var tmp_pool = new NativeGU.NativeMemoryPool(); + var exn = new NativeGU.NativeExceptionContext(tmp_pool); + + var cts = Native.pgf_lzr_concretize(Ptr, e.Ptr, exn.Ptr, tmp_pool.Ptr); + + var ctree = IntPtr.Zero; + NativeGU.gu_enum_next(cts, ref ctree, tmp_pool.Ptr); + + if (ctree == IntPtr.Zero) + { + return null; + } + + ctree = Native.pgf_lzr_wrap_linref(ctree, tmp_pool.Ptr); + + var builder = new Bracket.BracketBuilder(); + + var mem = Marshal.AllocHGlobal(Marshal.SizeOf<Native.PgfLinFuncs>()); + Marshal.StructureToPtr<Native.PgfLinFuncs>(builder.LinFuncs, mem, false); + + Native.pgf_lzr_linearize(Ptr, ctree, 0, ref mem, tmp_pool.Ptr); + + var b = builder.Build(); + + Marshal.FreeHGlobal(mem); + + return b; + } + } +} diff --git a/src/runtime/dotNet/Exceptions.cs b/src/runtime/dotNet/Exceptions.cs new file mode 100644 index 000000000..91193db74 --- /dev/null +++ b/src/runtime/dotNet/Exceptions.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PGFSharp +{ + + [Serializable] + public class PGFError : Exception + { + public PGFError() { } + public PGFError(string message) : base(message) { } + public PGFError(string message, Exception inner) : base(message, inner) { } + protected PGFError( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) : base(info, context) + { } + } + + + [Serializable] + public class ParseError : Exception + { + public ParseError() { } + public ParseError(string message) : base(message) { } + public ParseError(string message, Exception inner) : base(message, inner) { } + protected ParseError( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) : base(info, context) + { } + } + + [Serializable] + public class TypeError : Exception + { + public TypeError() { } + public TypeError(string message) : base(message) { } + public TypeError(string message, Exception inner) : base(message, inner) { } + protected TypeError( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) : base(info, context) + { } + } +} diff --git a/src/runtime/dotNet/Expr.cs b/src/runtime/dotNet/Expr.cs new file mode 100644 index 000000000..a65b281bf --- /dev/null +++ b/src/runtime/dotNet/Expr.cs @@ -0,0 +1,133 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace PGFSharp +{ + internal class UnsupportedExpr : Expr + { + internal UnsupportedExpr(IntPtr expr, NativeGU.NativeMemoryPool pool) : base(expr, pool) { } + public override R Accept<R>(IVisitor<R> visitor) + { + throw new NotImplementedException(); + } + } + + public abstract class Expr + { + internal IntPtr DataPtr => NativeGU.gu_variant_open(_ptr).Data; // PgfExprLit* + internal PgfExprTag Tag => (PgfExprTag)NativeGU.gu_variant_open(_ptr).Tag; + + internal IntPtr MkStringVariant(byte tag, string s, ref IntPtr out_) + { + var size = Encoding.UTF8.GetByteCount(s); + IntPtr slitPtr = NativeGU.gu_alloc_variant(tag, + (UIntPtr)(size + 1), UIntPtr.Zero, ref out_, _pool.Ptr); + Native.NativeString.CopyToPreallocated(s, slitPtr); + return slitPtr; + } + + /// <summary> + /// Read expression from string. + /// </summary> + /// <param name="exprStr"></param> + /// <returns></returns> + public Expr ReadExpr(string exprStr) + { + var tmp_pool = new NativeGU.NativeMemoryPool(); + var exn = new NativeGU.NativeExceptionContext(tmp_pool); + var result_pool = new NativeGU.NativeMemoryPool(); + using (var strNative = new Native.NativeString(exprStr)) + { + var in_ = NativeGU.gu_data_in(strNative.Ptr, strNative.Size, tmp_pool.Ptr); + var expr = Native.pgf_read_expr(in_, result_pool.Ptr, exn.Ptr); + if (exn.IsRaised || expr == IntPtr.Zero) + { + throw new PGFError(); + } + else + { + return Expr.FromPtr(expr, result_pool); + } + } + } + + internal enum PgfExprTag + { + PGF_EXPR_ABS, + PGF_EXPR_APP, + PGF_EXPR_LIT, + PGF_EXPR_META, + PGF_EXPR_FUN, + PGF_EXPR_VAR, + PGF_EXPR_TYPED, + PGF_EXPR_IMPL_ARG, + PGF_EXPR_NUM_TAGS // not used + }; + + public interface IVisitor<R> + { + R VisitLiteralInt(int value); + R VisitLiteralFloat(double value); + R VisitLiteralString(string value); + R VisitApplication(string fname, Expr[] args); + + //R VisitMetaVariable (int id); Dont' care about this for now... + + // Remove this, Function objects use VisitApplication with empty args instead. + //R VisitFunction (string fname); // Will this be used? + } + + public class Visitor<R> : IVisitor<R> + { + public Func<int, R> fVisitLiteralInt { get; set; } = null; + public R VisitLiteralInt(int x1) => fVisitLiteralInt(x1); + public Func<double, R> fVisitLiteralFlt { get; set; } = null; + public R VisitLiteralFloat(double x1) => fVisitLiteralFlt(x1); + public Func<string, R> fVisitLiteralStr { get; set; } = null; + public R VisitLiteralString(string x1) => fVisitLiteralStr(x1); + public Func<string, Expr[], R> fVisitApplication { get; set; } = null; + public R VisitApplication(string x1, Expr[] x2) => fVisitApplication(x1, x2); + } + + public abstract R Accept<R>(IVisitor<R> visitor); + + internal IntPtr _ptr = IntPtr.Zero; + internal NativeGU.NativeMemoryPool _pool; + internal IntPtr Ptr => _ptr; + + internal Expr() { } + internal Expr(IntPtr ptr, NativeGU.NativeMemoryPool pool) + { + _ptr = ptr; _pool = pool; + } + + // Factories + private static Dictionary<PgfExprTag, Func<IntPtr, NativeGU.NativeMemoryPool, Expr>> factories = + new Dictionary<PgfExprTag, Func<IntPtr, NativeGU.NativeMemoryPool, Expr>>{ + + { PgfExprTag.PGF_EXPR_LIT, (e, p) => LiteralExpr.FromPtr (e, p) }, + { PgfExprTag.PGF_EXPR_APP, (e, p) => new ApplicationExpr (e, p) }, + { PgfExprTag.PGF_EXPR_FUN, (e, p) => new FunctionExpr (e, p) }, + { PgfExprTag.PGF_EXPR_META, (e, p) => new MetaVariableExpr (e, p) } + }; + + internal static Expr FromPtr(IntPtr expr, NativeGU.NativeMemoryPool pool) + { + var Tag = (PgfExprTag)NativeGU.gu_variant_open(expr).Tag; + if (factories.ContainsKey(Tag)) + { + return factories[Tag](expr, pool); + } + else + return new UnsupportedExpr(expr, pool); + } + + public override string ToString() => + Native.ReadString((output,exn) => Native.pgf_print_expr(_ptr, IntPtr.Zero, 0, output, exn.Ptr)); + + } +} diff --git a/src/runtime/dotNet/Expr/Abstraction.cs b/src/runtime/dotNet/Expr/Abstraction.cs new file mode 100644 index 000000000..023208727 --- /dev/null +++ b/src/runtime/dotNet/Expr/Abstraction.cs @@ -0,0 +1,15 @@ +using System; +using System.Runtime.InteropServices; + +namespace PGFSharp +{ + /*public class Abs : Expression + { + public Abs () + { + } + } +*/ + +} + diff --git a/src/runtime/dotNet/Expr/Application.cs b/src/runtime/dotNet/Expr/Application.cs new file mode 100644 index 000000000..bcfb309a5 --- /dev/null +++ b/src/runtime/dotNet/Expr/Application.cs @@ -0,0 +1,57 @@ +using System; +using System.Runtime.InteropServices; +using System.Collections.Generic; +using System.Linq; + +namespace PGFSharp +{ + public class ApplicationExpr : Expr + { + public override R Accept<R> (IVisitor<R> visitor) + { + var args = new List<Expr> (); + var expr = this; + while (expr.Function is ApplicationExpr) { + args.Add (expr.Argument); + expr = expr.Function as ApplicationExpr; + } + args.Add (expr.Argument); + if (!(expr.Function is FunctionExpr)) + throw new ArgumentException (); + + args.Reverse (); + return visitor.VisitApplication ((expr.Function as FunctionExpr).Name, args.ToArray()); + } + + [StructLayout(LayoutKind.Sequential)] + private struct PgfExprApp { + public IntPtr Function; + public IntPtr Argument; + } + + private PgfExprApp Data => Marshal.PtrToStructure<PgfExprApp>(DataPtr); + + public Expr Function => Expr.FromPtr(Data.Function, _pool); + public Expr Argument => Expr.FromPtr(Data.Argument, _pool); + + internal ApplicationExpr(IntPtr ptr, NativeGU.NativeMemoryPool pool) : base(ptr, pool) { } + public ApplicationExpr(string fname, IEnumerable<Expr> args) + { + _pool = new NativeGU.NativeMemoryPool(); + MkStringVariant((byte)PgfExprTag.PGF_EXPR_FUN, fname, ref _ptr); + foreach (var arg in args) { + var fun = _ptr; + var exprApp = NativeGU.gu_alloc_variant((byte)PgfExprTag.PGF_EXPR_APP, + (UIntPtr)Marshal.SizeOf<PgfExprApp>(), UIntPtr.Zero, ref _ptr, _pool.Ptr); + + Native.EditStruct<PgfExprApp> (exprApp, (ref PgfExprApp app) => { + app.Function = fun; + app.Argument = arg.Ptr; + }); + } + + + } + } +} + diff --git a/src/runtime/dotNet/Expr/Function.cs b/src/runtime/dotNet/Expr/Function.cs new file mode 100644 index 000000000..900c605a0 --- /dev/null +++ b/src/runtime/dotNet/Expr/Function.cs @@ -0,0 +1,18 @@ +using System; +using System.Linq; +using System.Collections.Generic; + +namespace PGFSharp +{ + public class FunctionExpr : Expr + { + public override R Accept<R> (IVisitor<R> visitor) + { + return visitor.VisitApplication (Name, new Expr[] {}); + } + + internal FunctionExpr (IntPtr expr, NativeGU.NativeMemoryPool pool) : base(expr,pool) {} + public string Name => Native.NativeString.StringFromNativeUtf8(DataPtr); + } +} + diff --git a/src/runtime/dotNet/Expr/Literal.cs b/src/runtime/dotNet/Expr/Literal.cs new file mode 100644 index 000000000..daf515c63 --- /dev/null +++ b/src/runtime/dotNet/Expr/Literal.cs @@ -0,0 +1,127 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace PGFSharp +{ + public class LiteralStringExpr : LiteralExpr + { + internal LiteralStringExpr(IntPtr expr, NativeGU.NativeMemoryPool pool) : base(expr, pool) { } + public LiteralStringExpr(string s) : base() + { + _pool = new NativeGU.NativeMemoryPool(); + + var exprTag = (byte)(int)PgfExprTag.PGF_EXPR_LIT; + IntPtr litPtr = NativeGU.gu_alloc_variant(exprTag, + (UIntPtr)Marshal.SizeOf<NativePgfExprLit>(), UIntPtr.Zero, ref _ptr, _pool.Ptr); + + Native.EditStruct<NativePgfExprLit>(litPtr, (ref NativePgfExprLit lit) => { + MkStringVariant((byte)PgfLiteralTag.PGF_LITERAL_STR, s, ref lit.lit); + }); + } + + public override R Accept<R>(IVisitor<R> visitor) + { + return visitor.VisitLiteralString(Value); + } + + public string Value => Native.NativeString.StringFromNativeUtf8(LitDataPtr); + } + + public class LiteralIntExpr : LiteralExpr + { + internal LiteralIntExpr(IntPtr expr, NativeGU.NativeMemoryPool pool) : base(expr, pool) { } + public LiteralIntExpr(int val) : base() + { + Initialize<NativePgfLiteralInt>(PgfLiteralTag.PGF_LITERAL_INT, + (ref NativePgfLiteralInt ilit) => ilit.val = val); + } + + public override R Accept<R>(IVisitor<R> visitor) + { + return visitor.VisitLiteralInt(Value); + } + + public int Value => Marshal.PtrToStructure<NativePgfLiteralInt>(LitDataPtr).val; + + [StructLayout(LayoutKind.Sequential)] + private struct NativePgfLiteralInt { public int val; } + } + + public class LiteralFloatExpr : LiteralExpr + { + internal LiteralFloatExpr(IntPtr expr, NativeGU.NativeMemoryPool pool) : base(expr, pool) { } + public LiteralFloatExpr(double val) : base() + { + Initialize<NativePgfLiteralFlt>(PgfLiteralTag.PGF_LITERAL_FLT, + (ref NativePgfLiteralFlt flit) => flit.val = val); + } + + public override R Accept<R>(IVisitor<R> visitor) + { + return visitor.VisitLiteralFloat(Value); + } + + public double Value => Marshal.PtrToStructure<NativePgfLiteralFlt>(LitDataPtr).val; + + [StructLayout(LayoutKind.Sequential)] + private struct NativePgfLiteralFlt { public double val; } + } + + public abstract class LiteralExpr : Expr + { + internal LiteralExpr(IntPtr expr, NativeGU.NativeMemoryPool pool) : base(expr, pool) { } + internal LiteralExpr() { } + + internal new static Expr FromPtr(IntPtr expr, NativeGU.NativeMemoryPool pool) + { + var dataPtr = NativeGU.gu_variant_open(expr).Data; // PgfExprLit* + var data = Marshal.PtrToStructure<NativePgfExprLit>(dataPtr); + var literalTag = (PgfLiteralTag)NativeGU.gu_variant_open(data.lit).Tag; + + switch(literalTag) + { + case PgfLiteralTag.PGF_LITERAL_STR: + return new LiteralStringExpr(expr, pool); + case PgfLiteralTag.PGF_LITERAL_INT: + return new LiteralIntExpr(expr, pool); + case PgfLiteralTag.PGF_LITERAL_FLT: + return new LiteralFloatExpr(expr, pool); + default: + throw new ArgumentException(); + } + } + + internal void Initialize<TNative>(PgfLiteralTag litTag, Native.StructAction<TNative> setValue, UIntPtr? size = null) { + _pool = new NativeGU.NativeMemoryPool(); + + var exprTag = (byte)(int)PgfExprTag.PGF_EXPR_LIT; + IntPtr litPtr = NativeGU.gu_alloc_variant ( exprTag, + (UIntPtr)Marshal.SizeOf<NativePgfExprLit>(), UIntPtr.Zero, ref _ptr, _pool.Ptr); + + Native.EditStruct<NativePgfExprLit> (litPtr, (ref NativePgfExprLit lit) => { + IntPtr ilitPtr = NativeGU.gu_alloc_variant ((byte)litTag, + (UIntPtr)Marshal.SizeOf<TNative> (), UIntPtr.Zero, ref lit.lit, _pool.Ptr); + + Native.EditStruct<TNative>(ilitPtr, setValue); + }); + } + + // Deref DatPtr to det PgfExprLit. + private NativePgfExprLit Data => Marshal.PtrToStructure<NativePgfExprLit>(DataPtr); + + private PgfLiteralTag LiteralTag => (PgfLiteralTag) NativeGU.gu_variant_open(Data.lit).Tag; + internal IntPtr LitDataPtr => NativeGU.gu_variant_open(Data.lit).Data; + + internal enum PgfLiteralTag { + PGF_LITERAL_STR, + PGF_LITERAL_INT, + PGF_LITERAL_FLT, + PGF_LITERAL_NUM_TAGS + } + + [StructLayout(LayoutKind.Sequential)] + internal struct NativePgfExprLit { public IntPtr lit; } + } +} + diff --git a/src/runtime/dotNet/Expr/MetaVariable.cs b/src/runtime/dotNet/Expr/MetaVariable.cs new file mode 100644 index 000000000..30ead9004 --- /dev/null +++ b/src/runtime/dotNet/Expr/MetaVariable.cs @@ -0,0 +1,34 @@ +using System; +using System.Runtime.InteropServices; + +namespace PGFSharp +{ + public class MetaVariableExpr : Expr { + + internal MetaVariableExpr() { + _pool = new NativeGU.NativeMemoryPool(); + IntPtr exprMetaPtr = NativeGU.gu_alloc_variant ((byte)PgfExprTag.PGF_EXPR_META, + (UIntPtr)Marshal.SizeOf <NativePgfExprMeta>(), UIntPtr.Zero, ref _ptr, _pool.Ptr); + + Native.EditStruct<NativePgfExprMeta> (exprMetaPtr, (ref NativePgfExprMeta m) => m.Id = 0); + } + + internal MetaVariableExpr(IntPtr ptr, NativeGU.NativeMemoryPool pool) : base(ptr, pool) { } + + + public int Id => Data.Id; + private NativePgfExprMeta Data => Marshal.PtrToStructure<NativePgfExprMeta>(DataPtr); + + public override R Accept<R> (IVisitor<R> visitor) + { + // return visitor.VisitMetaVariable (Id); + + // Not supported yet. + throw new NotImplementedException(); + } + + [StructLayout(LayoutKind.Sequential)] + private struct NativePgfExprMeta { public int Id; } + } +} + diff --git a/src/runtime/dotNet/Native.cs b/src/runtime/dotNet/Native.cs new file mode 100644 index 000000000..346f85905 --- /dev/null +++ b/src/runtime/dotNet/Native.cs @@ -0,0 +1,306 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +/// <summary> +/// Portable grammar format PInvoke functions. +/// </summary> +namespace PGFSharp +{ + internal static class Native + { + + internal class NativeString : IDisposable + { + public IntPtr Ptr { get; private set; } + public int Size { get; private set; } + + public NativeString(string s) + { + Ptr = NativeUtf8FromString(s); + Size = Encoding.UTF8.GetByteCount(s); + } + + public void Dispose() + { + Marshal.FreeHGlobal(Ptr); + Ptr = IntPtr.Zero; + } + + public static IntPtr NativeUtf8FromString(string managedString) + { + int len = Encoding.UTF8.GetByteCount(managedString); + IntPtr nativeUtf8 = Marshal.AllocHGlobal(len + 1); + CopyToPreallocated(managedString, nativeUtf8, len); + return nativeUtf8; + } + + public static void CopyToPreallocated(string managedString, IntPtr ptr, int? len = null) + { + if (len == null) len = Encoding.UTF8.GetByteCount(managedString); + byte[] buffer = new byte[len.Value + 1]; + Encoding.UTF8.GetBytes(managedString, 0, managedString.Length, buffer, 0); + Marshal.Copy(buffer, 0, ptr, buffer.Length); + } + + public static string StringFromNativeUtf8(IntPtr nativeUtf8) + { + int len = 0; + while (Marshal.ReadByte(nativeUtf8, len) != 0) ++len; + byte[] buffer = new byte[len]; + Marshal.Copy(nativeUtf8, buffer, 0, buffer.Length); + return Encoding.UTF8.GetString(buffer); + } + } + + public delegate void StructAction<T>(ref T st); + public static void EditStruct<T>(IntPtr ptr, StructAction<T> f) + { + var str = Marshal.PtrToStructure<T>(ptr); + f(ref str); + Marshal.StructureToPtr<T>(str, ptr, false); + } + + const string LIBNAME = "pgf.dll"; + const CallingConvention CC = CallingConvention.Cdecl; + + + #region Basic + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern IntPtr pgf_read([MarshalAs(UnmanagedType.LPStr)] string fpath, IntPtr pool, IntPtr err); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern IntPtr pgf_read_in(IntPtr in_, IntPtr pool, IntPtr tmp_pool, IntPtr err); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern void pgf_concrete_load(IntPtr concr, IntPtr in_, IntPtr err); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern IntPtr pgf_abstract_name(IntPtr pgf); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern IntPtr pgf_concrete_name(IntPtr concr); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern IntPtr pgf_start_cat(IntPtr pgf, IntPtr pool); + + #endregion + + #region Linearization + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern void pgf_linearize(IntPtr concr, IntPtr expr, IntPtr out_, IntPtr err); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern IntPtr pgf_lzr_concretize(IntPtr concr, IntPtr expr, IntPtr err, IntPtr tmp_pool); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern IntPtr pgf_lzr_wrap_linref(IntPtr ctree, IntPtr tmp_pool); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern void pgf_lzr_linearize(IntPtr concr, IntPtr ctree, int lin_idx, ref IntPtr funcs, IntPtr tmp_pool); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern void pgf_lzr_linearize_simple(IntPtr concr, IntPtr ctree, int lin_idx, IntPtr out_, IntPtr exn, IntPtr tmp_pool); + #endregion + + + #region Iteration + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern void pgf_iter_languages(IntPtr pgf, ref GuMapItor itor, IntPtr err); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern void pgf_iter_categories(IntPtr pgf, ref GuMapItor itor, IntPtr err); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern void pgf_iter_functions(IntPtr pgf, ref GuMapItor itor, IntPtr err); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern void pgf_iter_functions_by_cat(IntPtr pgf, IntPtr catNameStr, ref GuMapItor itor, IntPtr err); + + #endregion + + #region Type + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern IntPtr pgf_function_type(IntPtr pgf, IntPtr funNameStr); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern IntPtr pgf_read_type(IntPtr in_, IntPtr pool, IntPtr err); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern void pgf_print_type(IntPtr expr, IntPtr ctxt, int prec, IntPtr output, IntPtr err); + #endregion + + #region Expression + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern void pgf_print_expr(IntPtr expr, IntPtr ctxt, int prec, IntPtr output, IntPtr err); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern IntPtr pgf_read_expr(IntPtr in_, IntPtr pool, IntPtr err); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern IntPtr pgf_compute(IntPtr pgf, IntPtr expr, IntPtr err, IntPtr tmp_pool, IntPtr res_pool); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern IntPtr pgf_generate_all(IntPtr pgf, IntPtr type, IntPtr err, IntPtr iter_pool, IntPtr out_pool); + #endregion + + #region Concrete + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern IntPtr pgf_parse_with_heuristics(IntPtr concr, IntPtr cat, IntPtr sentence, + double heuristics, IntPtr callbacks, IntPtr exn, + IntPtr parsePl, IntPtr exprPl); + #endregion + + #region Callbacks + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern IntPtr pgf_new_callbacks_map(IntPtr concr, IntPtr pool); + #endregion + + //public delegate void GuMapItorFn(IntPtr self, [MarshalAs(UnmanagedType.LPStr)] string key, IntPtr value, IntPtr err); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void GuMapItorFn(IntPtr self, IntPtr key, IntPtr value, IntPtr err); + + + /* + public delegate void GuFinalizerFn(IntPtr self); + + [StructLayout(LayoutKind.Sequential)] + public struct GuFinalizer + { + [MarshalAs(UnmanagedType.FunctionPtr)] + public GuFinalizerFn fn; + } + + [StructLayout(LayoutKind.Sequential)] + public struct PgfConcr + { + public IntPtr name, abstr, cflags, printnames, + ccats, fun_indices, coerce_idx, cncfuns, + sequences, cnccats; + public int total_cats; + public IntPtr pool; + GuFinalizer fin; + }*/ + + [StructLayout(LayoutKind.Sequential)] + public struct GuMapItor + { + [MarshalAs(UnmanagedType.FunctionPtr)] + public GuMapItorFn fn; + } + + [StructLayout(LayoutKind.Sequential)] + public struct PgfExprProb + { + public float prob; + public IntPtr expr; // PgfExpr type (not pointer, but typedef PgfExpr -> GuVariant -> uintptr_t) + } + + + #region Linearization callbacks + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void LinFuncSymbolToken(IntPtr self, IntPtr token); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void LinFuncBeginPhrase(IntPtr self, IntPtr cat, int fid, int lindex, IntPtr fun); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void LinFuncEndPhrase(IntPtr self, IntPtr cat, int fid, int lindex, IntPtr fun); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void LinFuncSymbolNonexistant(IntPtr self); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void LinFuncSymbolBinding(IntPtr self); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void LinFuncSymbolCapitalization(IntPtr self); + + [StructLayout(LayoutKind.Sequential)] + public struct PgfLinFuncs + { + [MarshalAs(UnmanagedType.FunctionPtr)] + public LinFuncSymbolToken symbol_token; + + [MarshalAs(UnmanagedType.FunctionPtr)] + public LinFuncBeginPhrase begin_prase; + + [MarshalAs(UnmanagedType.FunctionPtr)] + public LinFuncEndPhrase end_phrase; + + [MarshalAs(UnmanagedType.FunctionPtr)] + public LinFuncSymbolNonexistant symbol_ne; + + [MarshalAs(UnmanagedType.FunctionPtr)] + public LinFuncSymbolBinding symbol_bind; + + [MarshalAs(UnmanagedType.FunctionPtr)] + public LinFuncSymbolCapitalization symbol_capit; + } + + #endregion + + + /* + [StructLayout(LayoutKind.Sequential)] + public struct PGFClosure + { + public GuMapItor fn; + public IntPtr grammar; + public IntPtr obj; + }*/ + + public static string ReadString(Action<IntPtr, NativeGU.NativeExceptionContext> f) + { + var pool = new NativeGU.NativeMemoryPool(); + var exn = new NativeGU.NativeExceptionContext(pool); + var sbuf = NativeGU.gu_new_string_buf(pool.Ptr); + var output = NativeGU.gu_string_buf_out(sbuf); + f(output, exn); + if (exn.IsRaised) throw new Exception(); + var strPtr = NativeGU.gu_string_buf_freeze(sbuf, pool.Ptr); + var str = Native.NativeString.StringFromNativeUtf8(strPtr); + return str; + } + + public delegate void MapIterFunc(IntPtr pgf, ref GuMapItor fn, IntPtr err); + public delegate void IterNameFunc(IntPtr pgf, IntPtr name, ref GuMapItor fn, IntPtr err); + + public class IterFuncCurryName + { + private IntPtr name; + private IterNameFunc func; + public IterFuncCurryName(IterNameFunc f, IntPtr name) + { + this.func = f; + this.name = name; + } + + public void IterFunc(IntPtr pgf, ref GuMapItor fn, IntPtr err) + { + func(pgf, name, ref fn, err); + } + } + + public static void MapIter(MapIterFunc iter, IntPtr _pgf, Action<string, IntPtr> action) + { + var pool = new NativeGU.NativeMemoryPool(); + var exn = new NativeGU.NativeExceptionContext(pool); + var f = new GuMapItor() + { + fn = (self, key, value, _err) => + { + action(Native.NativeString.StringFromNativeUtf8(key), value); + if (exn.IsRaised) throw new Exception(); + } + }; + + iter(_pgf, ref f, exn.Ptr); + } + } +} diff --git a/src/runtime/dotNet/NativeGU.cs b/src/runtime/dotNet/NativeGU.cs new file mode 100644 index 000000000..2e7f11c0d --- /dev/null +++ b/src/runtime/dotNet/NativeGU.cs @@ -0,0 +1,127 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace PGFSharp +{ + internal static class NativeGU + { + + const string LIBNAME = "gu.dll"; + const CallingConvention CC = CallingConvention.Cdecl; + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern IntPtr gu_new_pool(); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern IntPtr gu_new_exn(IntPtr pool); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern void gu_pool_free(IntPtr pool); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern IntPtr get_gu_null_variant(); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern IntPtr gu_string_buf_out(IntPtr sbuf); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern IntPtr gu_new_string_buf(IntPtr pool); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern IntPtr gu_data_in(IntPtr str, int len, IntPtr pool); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern IntPtr gu_string_buf_freeze(IntPtr sbuf, IntPtr pool); + + [DllImport(LIBNAME, CallingConvention = CC)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool gu_exn_is_raised(IntPtr err); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern void gu_enum_next(IntPtr enum_, ref IntPtr outPtr, IntPtr pool); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern GuVariantInfo gu_variant_open(IntPtr variant); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern IntPtr gu_alloc_variant(byte tag, UIntPtr size, UIntPtr align, ref IntPtr out_, IntPtr pool); + + [DllImport(LIBNAME, CallingConvention = CC)] + public static extern IntPtr gu_make_variant(byte tag, UIntPtr size, UIntPtr align, ref IntPtr init, IntPtr pool); + + [StructLayout(LayoutKind.Sequential)] + public struct GuVariantInfo + { + public int Tag; + public IntPtr Data; + } + + + [StructLayout(LayoutKind.Sequential)] + public struct GuSeq + { + public UIntPtr length; + } + + public static uint SeqLength(IntPtr seqptr) + { + var seq = Marshal.PtrToStructure<GuSeq>(seqptr); + return (uint)seq.length; + } + + public static T gu_seq_index<T>(IntPtr seq, int index) + { + var dataPtr = seq + Marshal.SizeOf<GuSeq>(); + var hypoPtr = dataPtr + index * Marshal.SizeOf<T>(); + var hypo = Marshal.PtrToStructure<T>(hypoPtr); + return hypo; + } + + public class NativeMemoryPool + { + private IntPtr _ptr; + internal IntPtr Ptr => _ptr; + + public NativeMemoryPool() + { + _ptr = gu_new_pool(); + if (_ptr == IntPtr.Zero) throw new Exception(); + } + + ~NativeMemoryPool() + { + gu_pool_free(_ptr); + _ptr = IntPtr.Zero; + } + } + + public class NativeExceptionContext + { + private IntPtr _ptr; + internal IntPtr Ptr => _ptr; + + public NativeExceptionContext(NativeMemoryPool pool) + { + _ptr = gu_new_exn(pool.Ptr); + if (_ptr == IntPtr.Zero) throw new Exception(); + } + + public bool IsRaised => gu_exn_is_raised(_ptr); + } + + public static IEnumerable<IntPtr> IteratorToIEnumerable(IntPtr iterator, IntPtr pool) + { + IntPtr ptr = IntPtr.Zero; + NativeGU.gu_enum_next(iterator, ref ptr, pool); + while (ptr != IntPtr.Zero) + { + yield return ptr; + NativeGU.gu_enum_next(iterator, ref ptr, pool); + } + } + } +} diff --git a/src/runtime/dotNet/PGF.cs b/src/runtime/dotNet/PGF.cs new file mode 100644 index 000000000..e6efae1d5 --- /dev/null +++ b/src/runtime/dotNet/PGF.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace PGFSharp +{ + /// <summary> + /// Grammatical Framework grammar. + /// </summary> + public class PGF + { + private PGF() { } + + IntPtr _ptr; + NativeGU.NativeMemoryPool pool; + + /// <summary> + /// Read grammar from PGF file. + /// </summary> + /// <param name="fn">filename</param> + /// <returns></returns> + public static PGF ReadPGF(string fn) + { + var obj = new PGF(); + var exn = new NativeGU.NativeExceptionContext(new NativeGU.NativeMemoryPool()); + obj.pool = new NativeGU.NativeMemoryPool(); + obj._ptr = Native.pgf_read(fn, obj.pool.Ptr, exn.Ptr); + if (exn.IsRaised) + { + throw new PGFError($"Could not read PGF from file {fn}. ({System.IO.Directory.GetCurrentDirectory()})"); + } + return obj; + } + + public override string ToString() => $"Grammar:{Name}, {String.Join(", ", Languages.Keys)}"; + + /// <summary> + /// Name of the abstract grammar. + /// </summary> + public string Name => Native.NativeString.StringFromNativeUtf8(Native.pgf_abstract_name(_ptr)); + + /// <summary> + /// Default category of the grammar. + /// </summary> + public Type StartCat => Type.FromPtr(Native.pgf_start_cat(_ptr, pool.Ptr), pool); + + /// <summary> + /// All concrete grammars in the language. + /// </summary> + public Dictionary<string, Concr> Languages + { + get + { + var dict = new Dictionary<string, Concr>(); + Native.MapIter(Native.pgf_iter_languages, _ptr, (k, v) => dict[k] = Concr.FromPtr(this, dereference(v))); + return dict; + } + } + + private IntPtr dereference(IntPtr ptr) + { + return (IntPtr)Marshal.PtrToStructure(ptr, typeof(IntPtr)); + } + + /// <summary> + /// All categories in the abstract grammar. + /// </summary> + public IEnumerable<string> Categories => GetStringList(Native.pgf_iter_categories); + + /// <summary> + /// All functions in the abstract grammar. + /// </summary> + public IEnumerable<string> Functions => GetStringList(Native.pgf_iter_functions); + + /// <summary> + /// All functions producing the given category name. + /// </summary> + /// <param name="catName"></param> + /// <returns></returns> + public IEnumerable<string> FunctionByCategory(string catName) + { + using (var str = new Native.NativeString(catName)) + { + return GetStringList(new Native.IterFuncCurryName(Native.pgf_iter_functions_by_cat, str.Ptr).IterFunc); + } + } + + /// <summary> + /// Get type from function name. + /// </summary> + /// <param name="funName"></param> + /// <returns></returns> + public Type FunctionType(string funName) + { + using (var str = new Native.NativeString(funName)) + { + var typePtr = Native.pgf_function_type(_ptr, str.Ptr); + if (typePtr == IntPtr.Zero) throw new NullReferenceException(); + return Type.FromPtr(typePtr, pool); + } + } + + /// <summary> + /// Reduce expression. + /// </summary> + /// <param name="expr"></param> + /// <returns></returns> + public Expr Compute(Expr expr) + { + var tmp_pool = new NativeGU.NativeMemoryPool(); + var exn = new NativeGU.NativeExceptionContext(tmp_pool); + var result_pool = new NativeGU.NativeMemoryPool(); + var newExpr = Native.pgf_compute(_ptr, expr.Ptr, exn.Ptr, pool.Ptr, result_pool.Ptr); + + if (exn.IsRaised || newExpr == IntPtr.Zero) + { + throw new PGFError("Could not reduce expression."); + } + else + { + return Expr.FromPtr(newExpr, result_pool); + } + } + + /// <summary> + /// Enumerate all expressions in the given category. + /// </summary> + /// <param name="cat"></param> + /// <returns></returns> + public IEnumerable<Expr> GenerateAll(Type cat = null) + { + cat = cat ?? StartCat; + var tmp_pool = new NativeGU.NativeMemoryPool(); + var exn = new NativeGU.NativeExceptionContext(tmp_pool); + var result_pool = new NativeGU.NativeMemoryPool(); + IntPtr ptr = IntPtr.Zero; + var iterator = Native.pgf_generate_all(this._ptr, cat.Ptr, exn.Ptr, tmp_pool.Ptr, result_pool.Ptr); + + return NativeGU.IteratorToIEnumerable(iterator, tmp_pool.Ptr).Select(p => + { + var exprProb = Marshal.PtrToStructure<Native.PgfExprProb>(ptr); + return Expr.FromPtr(exprProb.expr, result_pool); + + }); + } + + private IEnumerable<string> GetStringList(Native.MapIterFunc f) + { + var c = new List<string>(); + Native.MapIter(f, _ptr, (k, v) => c.Add(k)); + return c; + } + } +} diff --git a/src/runtime/dotNet/PGFSharp.csproj b/src/runtime/dotNet/PGFSharp.csproj new file mode 100644 index 000000000..9c1942ade --- /dev/null +++ b/src/runtime/dotNet/PGFSharp.csproj @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{81C13B1B-FE00-4A56-A831-964D55032CDD}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>PGF</RootNamespace> + <AssemblyName>PGFSharp</AssemblyName> + <TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Bracket.cs" /> + <Compile Include="Concr.cs" /> + <Compile Include="Exceptions.cs" /> + <Compile Include="Native.cs" /> + <Compile Include="NativeGU.cs" /> + <Compile Include="PGF.cs" /> + <Compile Include="Type.cs" /> + <Compile Include="Expr.cs" /> + <Compile Include="Expr\Literal.cs" /> + <Compile Include="Expr\MetaVariable.cs" /> + <Compile Include="Expr\Application.cs" /> + <Compile Include="Expr\Function.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> + <ItemGroup> + <Folder Include="Expression\" /> + </ItemGroup> +</Project> diff --git a/src/runtime/dotNet/Properties/AssemblyInfo.cs b/src/runtime/dotNet/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..b1f1eb1ad --- /dev/null +++ b/src/runtime/dotNet/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("PGF")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("81c13b1b-fe00-4a56-a831-964d55032cdd")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("3.8.0.0")] +[assembly: AssemblyFileVersion("3.8.0.0")] diff --git a/src/runtime/dotNet/Type.cs b/src/runtime/dotNet/Type.cs new file mode 100644 index 000000000..9ec2c45d8 --- /dev/null +++ b/src/runtime/dotNet/Type.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace PGFSharp +{ + /// <summary> + /// A GF type. + /// </summary> + public class Type + { + private IntPtr _ptr; + internal IntPtr Ptr => _ptr; + private NativeGU.NativeMemoryPool _pool; + private Type() { } + + internal static Type FromPtr(IntPtr type, NativeGU.NativeMemoryPool pool) + { + var t = new Type(); + t._ptr = type; + t._pool = pool; + return t; + } + + public override string ToString() => + Native.ReadString((output,exn) => Native.pgf_print_type(_ptr, IntPtr.Zero, 0, output, exn.Ptr)); + + private PgfType Data => Marshal.PtrToStructure<PgfType>(_ptr); + + /// <summary> + /// Read type from string. + /// </summary> + /// <param name="typeStr"></param> + /// <returns></returns> + public Type ReadType(string typeStr) + { + var tmp_pool = new NativeGU.NativeMemoryPool(); + var exn = new NativeGU.NativeExceptionContext(tmp_pool); + var result_pool = new NativeGU.NativeMemoryPool(); + using (var strNative = new Native.NativeString(typeStr)) + { + var in_ = NativeGU.gu_data_in(strNative.Ptr, strNative.Size, tmp_pool.Ptr); + var typ = Native.pgf_read_type(in_, result_pool.Ptr, exn.Ptr); + if (exn.IsRaised || typ == IntPtr.Zero) + { + throw new PGFError(); + } + else + { + return Type.FromPtr(typ, result_pool); + } + } + } + + /// <summary> + /// Get the hypotheses of a type (function argument types). + /// </summary> + public IEnumerable<Type> Hypotheses + { + get + { + var n_hypos = NativeGU.SeqLength(Data.hypos); + for (int i = 0; i < n_hypos; i++) + { + var hypo = NativeGU.gu_seq_index<PgfHypo>(Data.hypos, i); + var type = Type.FromPtr(hypo.type, this._pool); + yield return type; + } + } + } + + [StructLayout(LayoutKind.Sequential)] + private struct PgfType + { + public IntPtr hypos; // GuSeq of PgfHypo + public IntPtr cid; + public UIntPtr n_exprs; + public IntPtr exprs; + } + + [StructLayout(LayoutKind.Sequential)] + private struct PgfHypo + { + public int pgfBindType; // enum + public IntPtr cid; // PgfCId (string) + public IntPtr type; // PgfType* + } + } +} |
