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 stack = new Stack (); + 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 _children = new List (); + 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 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 +{ + /// + /// Concrete grammar. All concrete grammars are available from the (Abstract) class. + /// + public class Concr + { + internal IntPtr Ptr { get; private set; } + + /// + /// Abstract grammar for this language. + /// + 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; + } + + /// + /// Name of the grammar. + /// + public string Name => Native.NativeString.StringFromNativeUtf8(Native.pgf_concrete_name(Ptr)); + public override string ToString() => $"Concrete:{Name} of {PGF.Name}"; + + /// + /// Parse given input string in the concrete grammar. + /// + /// Input string to be parsed. + /// Category (Type) to parse. + /// Heuristic (see the GF C runtime docs). + /// Callback function. + /// Callback function. + /// Enumerates pairs of (abstract grammar) expressions and corresponding probability. + public IEnumerable> 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); + } + } + } + } + + /// + /// Linearize expression, i.e. produce a string in the concrete grammar from an expression in the abstract grammar. + /// + /// + /// + 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); + } + } + + /// + /// Get all possible linearization for an expression (see ). + /// + /// + /// + public IEnumerable 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); + } + + /// + /// Get the bracketed (structured) linearization of an expression. + /// + /// + /// + 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()); + Marshal.StructureToPtr(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(IVisitor 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; + } + + /// + /// Read expression from string. + /// + /// + /// + 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 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 : IVisitor + { + public Func fVisitLiteralInt { get; set; } = null; + public R VisitLiteralInt(int x1) => fVisitLiteralInt(x1); + public Func fVisitLiteralFlt { get; set; } = null; + public R VisitLiteralFloat(double x1) => fVisitLiteralFlt(x1); + public Func fVisitLiteralStr { get; set; } = null; + public R VisitLiteralString(string x1) => fVisitLiteralStr(x1); + public Func fVisitApplication { get; set; } = null; + public R VisitApplication(string x1, Expr[] x2) => fVisitApplication(x1, x2); + } + + public abstract R Accept(IVisitor 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> factories = + new Dictionary>{ + + { 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 (IVisitor visitor) + { + var args = new List (); + 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(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 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(), UIntPtr.Zero, ref _ptr, _pool.Ptr); + + Native.EditStruct (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 (IVisitor 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(), UIntPtr.Zero, ref _ptr, _pool.Ptr); + + Native.EditStruct(litPtr, (ref NativePgfExprLit lit) => { + MkStringVariant((byte)PgfLiteralTag.PGF_LITERAL_STR, s, ref lit.lit); + }); + } + + public override R Accept(IVisitor 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(PgfLiteralTag.PGF_LITERAL_INT, + (ref NativePgfLiteralInt ilit) => ilit.val = val); + } + + public override R Accept(IVisitor visitor) + { + return visitor.VisitLiteralInt(Value); + } + + public int Value => Marshal.PtrToStructure(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(PgfLiteralTag.PGF_LITERAL_FLT, + (ref NativePgfLiteralFlt flit) => flit.val = val); + } + + public override R Accept(IVisitor visitor) + { + return visitor.VisitLiteralFloat(Value); + } + + public double Value => Marshal.PtrToStructure(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(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(PgfLiteralTag litTag, Native.StructAction 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(), UIntPtr.Zero, ref _ptr, _pool.Ptr); + + Native.EditStruct (litPtr, (ref NativePgfExprLit lit) => { + IntPtr ilitPtr = NativeGU.gu_alloc_variant ((byte)litTag, + (UIntPtr)Marshal.SizeOf (), UIntPtr.Zero, ref lit.lit, _pool.Ptr); + + Native.EditStruct(ilitPtr, setValue); + }); + } + + // Deref DatPtr to det PgfExprLit. + private NativePgfExprLit Data => Marshal.PtrToStructure(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 (), UIntPtr.Zero, ref _ptr, _pool.Ptr); + + Native.EditStruct (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(DataPtr); + + public override R Accept (IVisitor 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; + +/// +/// Portable grammar format PInvoke functions. +/// +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(ref T st); + public static void EditStruct(IntPtr ptr, StructAction f) + { + var str = Marshal.PtrToStructure(ptr); + f(ref str); + Marshal.StructureToPtr(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 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 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(seqptr); + return (uint)seq.length; + } + + public static T gu_seq_index(IntPtr seq, int index) + { + var dataPtr = seq + Marshal.SizeOf(); + var hypoPtr = dataPtr + index * Marshal.SizeOf(); + var hypo = Marshal.PtrToStructure(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 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 +{ + /// + /// Grammatical Framework grammar. + /// + public class PGF + { + private PGF() { } + + IntPtr _ptr; + NativeGU.NativeMemoryPool pool; + + /// + /// Read grammar from PGF file. + /// + /// filename + /// + 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)}"; + + /// + /// Name of the abstract grammar. + /// + public string Name => Native.NativeString.StringFromNativeUtf8(Native.pgf_abstract_name(_ptr)); + + /// + /// Default category of the grammar. + /// + public Type StartCat => Type.FromPtr(Native.pgf_start_cat(_ptr, pool.Ptr), pool); + + /// + /// All concrete grammars in the language. + /// + public Dictionary Languages + { + get + { + var dict = new Dictionary(); + 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)); + } + + /// + /// All categories in the abstract grammar. + /// + public IEnumerable Categories => GetStringList(Native.pgf_iter_categories); + + /// + /// All functions in the abstract grammar. + /// + public IEnumerable Functions => GetStringList(Native.pgf_iter_functions); + + /// + /// All functions producing the given category name. + /// + /// + /// + public IEnumerable FunctionByCategory(string catName) + { + using (var str = new Native.NativeString(catName)) + { + return GetStringList(new Native.IterFuncCurryName(Native.pgf_iter_functions_by_cat, str.Ptr).IterFunc); + } + } + + /// + /// Get type from function name. + /// + /// + /// + 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); + } + } + + /// + /// Reduce expression. + /// + /// + /// + 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); + } + } + + /// + /// Enumerate all expressions in the given category. + /// + /// + /// + public IEnumerable 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(ptr); + return Expr.FromPtr(exprProb.expr, result_pool); + + }); + } + + private IEnumerable GetStringList(Native.MapIterFunc f) + { + var c = new List(); + 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 @@ + + + + + Debug + AnyCPU + {81C13B1B-FE00-4A56-A831-964D55032CDD} + Library + Properties + PGF + PGFSharp + v4.5.1 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 +{ + /// + /// A GF type. + /// + 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(_ptr); + + /// + /// Read type from string. + /// + /// + /// + 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); + } + } + } + + /// + /// Get the hypotheses of a type (function argument types). + /// + public IEnumerable Hypotheses + { + get + { + var n_hypos = NativeGU.SeqLength(Data.hypos); + for (int i = 0; i < n_hypos; i++) + { + var hypo = NativeGU.gu_seq_index(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* + } + } +}