public BindingContext BuildContext(BindingContext callingContext, IUnboundDecl parameterType, IBoundDecl argType, ref IEnumerable <IBoundDecl> typeArgs, out bool canInferArgs) { // try to infer the args if not passed in IList <IBoundDecl> inferredTypeArgs = TypeArgInferrer.Infer(TypeParameters, parameterType, argType); canInferArgs = inferredTypeArgs != null; if (canInferArgs) { typeArgs = inferredTypeArgs; } if (typeArgs.IsEmpty()) { typeArgs = null; } // include the open namespaces of the calling context. this was the instantiated // generic has access to everything that the instantiation call site has access // to var searchSpace = new NameSearchSpace(BaseType.SearchSpace, callingContext.SearchSpace); return(new BindingContext(callingContext.Compiler, searchSpace, TypeParameters, typeArgs)); }
/// <summary> /// Infers the types of the given collection of named type arguments from the given collection /// of parameters. /// </summary> /// <param name="typeArgNames">The names of the type parameters.</param> /// <param name="parameters"></param> /// <returns></returns> public static IList <IBoundDecl> Infer(IEnumerable <string> typeParameters, IUnboundDecl parameterType, IBoundDecl argType) { var inferrer = new TypeArgInferrer(typeParameters); inferrer.mParamTypes.Push(parameterType); bool dummy = argType.Accept(inferrer); inferrer.mParamTypes.Pop(); // if the inference failed (like from a type collision) then fail if (inferrer.mFailed) { return(null); } // if any type argument is left unfilled then fail if (inferrer.mTypeArguments.Contains(null)) { return(null); } return(inferrer.mTypeArguments); }
/// <summary> /// Creates a new unbound declaration. /// </summary> public Decl(IUnboundDecl unbound) { if (unbound == null) { throw new ArgumentNullException("unbound"); } Unbound = unbound; }
public UnionCase(string name, IUnboundDecl valueType, int index) { if (valueType == null) { throw new ArgumentNullException("valueType"); } Name = name; ValueType = new Decl(valueType); Index = index; }
// <-- LPAREN ParamDecl? ARROW TypeDecl? RPAREN private FuncType FnArgsDecl(List <string> paramNames) { Consume(TokenType.LeftParen); var arg = CurrentIs(TokenType.RightArrow) ? Decl.Unit : ParamDecl(paramNames); var position = Consume(TokenType.RightArrow).Position; IUnboundDecl returnType = CurrentIs(TokenType.RightParen) ? Decl.Unit : TypeDecl(); Consume(TokenType.RightParen); return(new FuncType(position, arg, returnType)); }
public static T Match <T>(this IUnboundDecl decl, Func <AtomicDecl, T> atomicCallback, Func <FuncType, T> funcCallback, Func <RecordType, T> recordCallback, Func <TupleType, T> tupleCallback, Func <NamedType, T> namedCallback) { if (decl == null) { throw new ArgumentNullException("decl"); } var atomic = decl as AtomicDecl; if (atomic != null) { return(atomicCallback(atomic)); } var func = decl as FuncType; if (func != null) { return(funcCallback(func)); } var record = decl as RecordType; if (record != null) { return(recordCallback(record)); } var tuple = decl as TupleType; if (tuple != null) { return(tupleCallback(tuple)); } var named = decl as NamedType; if (named != null) { return(namedCallback(named)); } throw new ArgumentException("Unknown declaration type."); }
public FuncType(Position position, IUnboundDecl parameter, IUnboundDecl returnType) { if (parameter == null) { throw new ArgumentNullException("parameter"); } if (returnType == null) { throw new ArgumentNullException("returnType"); } Position = position; Parameter = new Decl(parameter); Return = new Decl(returnType); }
public static IUnboundDecl Clone(this IUnboundDecl decl) { return(decl.Match <IUnboundDecl>( // atomic types are immutable, so we can reuse it atomic => atomic, func => func.CloneFunc(), record => { var fields = new Dictionary <string, IUnboundDecl>(); foreach (var field in record.Fields) { fields.Add(field.Key, field.Value.Clone()); } return new RecordType(fields); }, tuple => new TupleType(tuple.Fields.Select(field => field.Clone())), // named types are immutable, so we can reuse it named => named)); }
public static IUnboundDecl[] Expand(this IUnboundDecl decl) { // the unit type expands to no values if (ReferenceEquals(decl, Decl.Unit)) { return(new IUnboundDecl[0]); } // a tuple expands to its fields TupleType tuple = decl as TupleType; if (tuple != null) { return(tuple.Fields.ToArray()); } // everything else expands to just itself return(new IUnboundDecl[] { decl }); }
// <-- (NAME (TypeDecl)? LINE)* private List <UnionCase> UnionCases() { var cases = new List <UnionCase>(); while (CurrentIs(TokenType.Name)) { var name = Consume(TokenType.Name).StringValue; IUnboundDecl type = Decl.Unit; if (!CurrentIs(TokenType.Line)) { type = TypeDecl(); } Consume(TokenType.Line); cases.Add(new UnionCase(name, type, cases.Count)); } return(cases); }
public static IBoundDecl Bind(BindingContext context, IUnboundDecl unbound) { return(unbound.Match <IBoundDecl>( // atomics are already bound atomic => atomic, func => { Bind(context, func); return func; }, record => { var fields = new Dictionary <string, IBoundDecl>(); foreach (var field in record.Fields) { fields.Add(field.Key, Bind(context, field.Value)); } return new BoundRecordType(fields); }, tuple => new BoundTupleType(tuple.Fields.Select(field => Bind(context, field))), named => BindNamed(context, named))); }
public Field(string name, IUnboundDecl type) : this(name, type, 0) { }
/// <summary> /// Binds this declaration to the given binder. /// </summary> public void Bind(Func<IUnboundDecl, IBoundDecl> binder) { if (binder == null) throw new ArgumentNullException("binder"); if (IsBound) throw new InvalidOperationException("Cannot bind a Decl that is already bound."); Bound = binder(Unbound); // discard the unbound one now. makes sure we're clear on what state we expect // the declaration to be in. Unbound = null; }
/// <summary> /// Creates a new unbound declaration. /// </summary> public Decl(IUnboundDecl unbound) { if (unbound == null) throw new ArgumentNullException("unbound"); Unbound = unbound; }
public FuncRefExpr(Position position, NameExpr name, IUnboundDecl paramType) { Position = position; Name = name; ParamType = paramType; }
public Field(string name, IUnboundDecl type, byte index) : this(name, index) { Type = new Decl(type); }
/// <summary> /// Instantiates a new instance of a zero-length array. /// </summary> /// <param name="position">Where the expression occurs in the source file.</param> /// <param name="elementType">The element type. This must be explicitly passed in since /// it cannot be inferred from an element.</param> public ArrayExpr(Position position, IUnboundDecl elementType) { Position = position; mElementType = elementType; }
public void Define(string name, IUnboundDecl type) { Fields.Add(new Field(name, type, (byte)Fields.Count)); }
public NamedType(string name) { Position = Position.None; Name = name; mTypeArgs = new IUnboundDecl[0]; }