private static RppFunc CreateApply(RTypeName className, IEnumerable<ResolvableType> classParams) { int paramIndex = 0; IEnumerable<IRppParam> funcParams = classParams.Select(t => new RppParam($"_{paramIndex++}", t)).ToList(); RppNew newExpr = new RppNew(new ResolvableType(className), funcParams.Select(p => new RppId(p.Name, p))); return new RppFunc("apply", funcParams, new ResolvableType(className), newExpr); }
private static RppClass CreateCompanion(string name, IEnumerable<RppField> classParamsCollection) { RTypeName typeName = new RTypeName(name); IEnumerable<RppField> classParams = classParamsCollection as IList<RppField> ?? classParamsCollection.ToList(); var classParamsTypes = classParams.Select(p => p.Type).ToList(); RppFunc apply = CreateApply(typeName, classParamsTypes); RppFunc unapply = CreateUnapply(typeName, classParams); var exprs = List(apply, unapply); RppClass clazz = new RppClass(ClassKind.Object, new HashSet<ObjectModifier>(), name, Collections.NoFields, exprs, Collections.NoVariantTypeParams, RppBaseConstructorCall.Object); return clazz; }
private static RTypeName CreateTupleType(IEnumerable<string> names) { IEnumerable<string> typeNames = names as IList<string> ?? names.ToList(); string tupleTypeNameString = "Tuple" + typeNames.Count(); RTypeName tuppleType = new RTypeName(tupleTypeNameString); typeNames.Select(n => new RTypeName(n)).ForEach(tuppleType.AddGenericArgument); return tuppleType; }
private static ResolvableType CreateUnapplyReturnType(IEnumerable<string> typeNames) { IEnumerable<string> names = typeNames as IList<string> ?? typeNames.ToList(); if (!names.Any()) { return ResolvableType.BooleanTy; } if (names.Count() == 1) { RTypeName optionType = new RTypeName("Option"); optionType.AddGenericArgument(new RTypeName(names.First())); return new ResolvableType(optionType); } else { RTypeName optionType = new RTypeName("Option"); RTypeName tuppleType = CreateTupleType(names); optionType.AddGenericArgument(tuppleType); return new ResolvableType(optionType); } }
private static RTypeName CreateTupleTypeName(ICollection<RTypeName> paramTypes) { RTypeName tupleType = new RTypeName(CreateTupleClassName(paramTypes.Count)); paramTypes.ForEach(tupleType.AddGenericArgument); return tupleType; }
private static bool IsAction(RTypeName returnType) { return returnType.Name.Equals("Unit"); }
/// <summary> /// Creates Function[paramCount] type name if return type is not Unit. /// If it's Unit then it creates Action[paramCount]. /// </summary> private static RTypeName CreateClosureTypeName(ICollection<RTypeName> paramTypes, RTypeName returnType) { bool isAction = IsAction(returnType); string baseTypeName = isAction ? "Action" : "Function"; RTypeName closureType = new RTypeName(baseTypeName + paramTypes.Count); paramTypes.ForEach(closureType.AddGenericArgument); if (!isAction) { closureType.AddGenericArgument(returnType); } return closureType; }
// Consume follow is needed to handle pattern matching case: // case x: Foo => x.length // without consumeFollow false it will parse and closure type (Foo => x) which is incorrect public bool ParseType(out RTypeName type, bool consumeFollow = true) { if (Require(RppLexer.Id)) { IToken typeNameToken = _lastToken; if (Require(RppLexer.OP_LBracket)) { RTypeName genericType = new RTypeName(typeNameToken); type = genericType; RTypeName subType; if (!ParseType(out subType)) { RaiseSyntaxError("Type is expected"); } genericType.AddGenericArgument(subType); while (true) { if (Require(RppLexer.OP_RBracket)) { break; } if (Require(RppLexer.OP_Comma)) { if (!ParseType(out subType)) { RaiseSyntaxError("Type is expected"); } genericType.AddGenericArgument(subType); } else { RaiseSyntaxError("Expected comma"); } } return true; } // A => B if (consumeFollow && Require(RppLexer.OP_Follow)) { RTypeName returnType; if (!ParseType(out returnType)) { RaiseSyntaxError("Type is expected"); } type = CreateClosureTypeName(new List<RTypeName> {new RTypeName(typeNameToken)}, returnType); return true; } type = new RTypeName(typeNameToken); return true; } // (A, B) => C // (A => B) if (Require(RppLexer.OP_LParen)) { bool closingParenRequired = true; RTypeName returnType; IList<RTypeName> paramTypes = new List<RTypeName>(); while (true) { if (Require(RppLexer.OP_RParen)) { closingParenRequired = false; break; } if (Peek(RppLexer.OP_Follow)) { break; } if (paramTypes.Count > 0) { Expect(RppLexer.OP_Comma); } RTypeName paramType; if (ParseType(out paramType)) { paramTypes.Add(paramType); } else { RaiseSyntaxError("Type is expected"); } } if (!Require(RppLexer.OP_Follow)) { // (A => A) if (paramTypes.Count == 1) { type = paramTypes[0]; return true; } // (A, B, C) type = CreateTupleTypeName(paramTypes); return true; } if (!ParseType(out returnType)) { RaiseSyntaxError("Type is expected"); } if (closingParenRequired) { Expect(RppLexer.OP_RParen); } type = CreateClosureTypeName(paramTypes, returnType); return true; } type = null; return false; }
public RppVariantTypeParam([NotNull] string name, TypeVariant variant, [CanBeNull] RTypeName constraintTypeName) : base(name) { Variant = variant; _constraint = constraintTypeName; }
private bool ParseVariantTypeParam(out RppVariantTypeParam typeParam) { TypeVariant variant = TypeVariant.Invariant; // "A" bool requireId = false; if (Require(RppLexer.OP_Unary)) { if (_lastToken.Text == "+") // "+A" { variant = TypeVariant.Covariant; } else if (_lastToken.Text == "-") // "-A" { variant = TypeVariant.Contravariant; } else { RaiseSyntaxError("Expected '+' or '-'"); } requireId = true; } if (Require(RppLexer.Id)) { string typeParamName = _lastToken.Text; RTypeName constraint = null; if (Require(RppLexer.OP_Upper)) { Expect(RppLexer.Id); constraint = new RTypeName(_lastToken); } typeParam = new RppVariantTypeParam(typeParamName, variant, constraint); return true; } if (requireId) { RaiseSyntaxError("Expected identifier"); } typeParam = null; return false; }
private static RTypeName Reconstruct(RType type) { RTypeName typeName = new RTypeName(type.Name); type.GenericArguments.ForEach(ga => typeName.AddGenericArgument(Reconstruct(ga))); return typeName; }
public ResolvableType([NotNull] RType type) { _type = type; Name = new RTypeName(type.Name); // TODO this doesn't work for generics }
protected bool Equals(RTypeName other) { // TODO need to Equals also generic params return string.Equals(Name, other.Name); }
public void AddGenericArgument(RTypeName genericArgument) { _params.Add(genericArgument); }
public static RppParam Param(string name, RTypeName typeName) { return new RppParam(name, new ResolvableType(typeName)); }
public IList<IRppNode> ParseClassTemplateOpt(out RTypeName baseClassType, out IList<IRppExpr> constrArgs) { baseClassType = null; constrArgs = Collections.NoExprs; if (Require(RppLexer.KW_Extends)) { if (Require(RppLexer.Id)) { baseClassType = new RTypeName(_lastToken); } else { RaiseSyntaxError("Expected identifier"); } IList<RTypeName> typeArgs = ParseTypeParamClause(); typeArgs.ForEach(baseClassType.AddGenericArgument); var args = ParseArgsOpt(); constrArgs = args; } return ParseTemplateBody(); }
public RppTypedPattern(IToken varid, RTypeName typeName) { Token = varid; Name = varid.Text; _resolvableType = new ResolvableType(typeName); }