FunctionEvaluation(MemberSymbol method, AbstractSymbolValueProvider baseValueProvider, Dictionary<DVariable, ISymbolValue> args) { vp = new InterpretationContext(baseValueProvider); foreach (var kv in args) vp[kv.Key] = kv.Value; }
public static MemberSymbol FillMethodReturnType(MemberSymbol mr, ResolverContextStack ctxt) { if (mr == null || ctxt == null) return mr; var dm = mr.Definition as DMethod; ctxt.CurrentContext.IntroduceTemplateParameterTypes(mr); if (dm != null) { var returnType=GetMethodReturnType(dm, ctxt); mr = new MemberSymbol(dm, returnType, mr.DeclarationOrExpressionBase); } ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(mr); return mr; }
ISemantic E(NewExpression nex) { // http://www.d-programming-language.org/expression.html#NewExpression ISemantic[] possibleTypes = null; if (nex.Type is IdentifierDeclaration) possibleTypes = TypeDeclarationResolver.Resolve((IdentifierDeclaration)nex.Type, ctxt, filterForTemplateArgs: false); else possibleTypes = TypeDeclarationResolver.Resolve(nex.Type, ctxt); var ctors = new Dictionary<DMethod, TemplateIntermediateType>(); if (possibleTypes == null) return null; foreach (var t in possibleTypes) { var ct = DResolver.StripAliasSymbol(t as AbstractType) as TemplateIntermediateType; if (ct!=null && !ct.Definition.ContainsAttribute(DTokens.Abstract)) foreach (var ctor in GetConstructors(ct)) ctors.Add(ctor, ct); } MemberSymbol finalCtor = null; var kvArray = ctors.ToArray(); /* * TODO: Determine argument types and filter out ctor overloads. */ if (kvArray.Length != 0) finalCtor = new MemberSymbol(kvArray[0].Key, kvArray[0].Value, nex); else if (possibleTypes.Length != 0) return AbstractType.Get(possibleTypes[0]); return finalCtor; }
private static void GenerateForStatement(ScriptGenerator generator, MemberSymbol symbol, ForStatement statement) { if (statement.Body == null) { return; } ScriptTextWriter writer = generator.Writer; writer.Write("for "); writer.Write("("); if (statement.Initializers != null) { ExpressionGenerator.GenerateExpressionList(generator, symbol, statement.Initializers); } else if (statement.Variables != null) { GenerateVariableDeclarations(generator, symbol, statement.Variables); } writer.Write("; "); if (statement.Condition != null) { ExpressionGenerator.GenerateExpression(generator, symbol, statement.Condition); } writer.Write("; "); if (statement.Increments != null) { ExpressionGenerator.GenerateExpressionList(generator, symbol, statement.Increments); } writer.WriteLine(") {"); writer.Indent++; GenerateStatement(generator, symbol, statement.Body); writer.Indent--; writer.Write("}"); writer.WriteLine(); }
public void Visit(AdvancedReturnStatementNode node) { ValueAstEvaluator valueEvaluator = new ValueAstEvaluator(sender); MathExpressionAstEvaluator exprEvaluator = new MathExpressionAstEvaluator(); Cell cell = sender.GetCurrentCell(); Symbol sym = Stbl.st.Retrieve(node.Identifier.Label); if (sym is StateSymbol s) { try { // Set state members StateSymbol state = s.Copy(); foreach (ReturnMemberNode rNode in node.ReturnMembers) { MemberSymbol member = state.RetrieveMember(rNode.ID.Label); switch (rNode.Value) { case ExpressionNode valueNode: member.SetValue(exprEvaluator.Visit(valueNode)); break; case StringValueNode valueNode: member.SetValue(valueNode.Value); break; default: throw new TheLanguageErrorException($"ReturnMember value cannot be of type \'{ rNode.Value.GetType().Name }\'"); } } sender.SetCell(cell, state); } catch (TheLanguageErrorException e) { throw new TheLanguageErrorException($"Return statement \'{ node.Identifier.Label }\'", e); } } else { throw new TheLanguageErrorException($"Return statement. Unexpected type { sym } expected State"); } sender.ReturnStatementHasBeenHit = true; }
public static AbstractType DemangleAndResolve(string mangledString, ResolutionContext ctxt, out ITypeDeclaration qualifier) { bool isCFunction; Demangler.Demangle(mangledString, out qualifier, out isCFunction); // Seek for C functions | Functions that have no direct module association (e.g. _Dmain) if (qualifier is IdentifierDeclaration && qualifier.InnerDeclaration == null) { var id = (qualifier as IdentifierDeclaration).Id; return(Resolver.ASTScanner.NameScan.ScanForCFunction(ctxt, id, isCFunction)); } bool seekCtor = false; if (qualifier is IdentifierDeclaration) { var id = (qualifier as IdentifierDeclaration).Id; if ((seekCtor = (id == DMethod.ConstructorIdentifier)) || id == "__Class" || id == "__ModuleInfo") { qualifier = qualifier.InnerDeclaration; } } var resSym = TypeDeclarationResolver.ResolveSingle(qualifier, ctxt); if (seekCtor && resSym is UserDefinedType) { var ctor = (resSym as TemplateIntermediateType).Definition[DMethod.ConstructorIdentifier].FirstOrDefault(); if (ctor != null) { resSym = new MemberSymbol(ctor as DNode, null, null); } } return(resSym); }
private static void GenerateWhileStatement(ScriptGenerator generator, MemberSymbol symbol, WhileStatement statement) { if (statement.Body == null) { return; } ScriptTextWriter writer = generator.Writer; if (statement.PreCondition) { writer.Write("while ("); ExpressionGenerator.GenerateExpression(generator, symbol, statement.Condition); writer.WriteLine(") {"); } else { writer.WriteLine("do {"); } writer.Indent++; GenerateStatement(generator, symbol, statement.Body); writer.Indent--; if (statement.PreCondition) { writer.WriteLine("}"); } else { writer.Write("} while ("); ExpressionGenerator.GenerateExpression(generator, symbol, statement.Condition); writer.WriteLine(");"); } }
private static void GenerateBaseInitializerExpression(ScriptGenerator generator, MemberSymbol symbol, BaseInitializerExpression expression) { ScriptTextWriter writer = generator.Writer; Debug.Assert(symbol.Parent is ClassSymbol); ClassSymbol baseClass = ((ClassSymbol)symbol.Parent).BaseClass; Debug.Assert(baseClass != null); if (baseClass.GenericArguments?.Any() ?? false) { writer.Write(DSharpStringResources.ScriptExportMember("getGenericConstructor")); writer.Write("("); writer.Write(baseClass.FullGeneratedName); writer.Write(", "); generator.WriteGenericTypeArgumentsMap(baseClass.GenericArguments, baseClass.GenericParameters); writer.Write(")"); } else { writer.Write(baseClass.FullGeneratedName); } writer.Write(".call(this"); if (expression.Parameters != null) { writer.Write(", "); GenerateExpressionList(generator, symbol, expression.Parameters); } writer.Write(")"); }
/// <summary> /// The variable's or method's base type will be resolved (if auto type, the intializer's type will be taken). /// A class' base class will be searched. /// etc.. /// </summary> public static AbstractType HandleNodeMatch( INode m, ResolutionContext ctxt, AbstractType resultBase = null, object typeBase = null) { AbstractType ret = null; // See https://github.com/aBothe/Mono-D/issues/161 int stkC; if (stackCalls == null) { stackCalls = new Dictionary<INode, int>(); stackCalls[m] = stkC = 1; } else if (stackCalls.TryGetValue(m, out stkC)) stackCalls[m] = ++stkC; else stackCalls[m] = stkC = 1; /* * Pushing a new scope is only required if current scope cannot be found in the handled node's hierarchy. * Edit: No, it is required nearly every time because of nested type declarations - then, we do need the * current block scope. */ bool popAfterwards; { var newScope = m is IBlockNode ? (IBlockNode)m : m.Parent as IBlockNode; popAfterwards = ctxt.ScopedBlock != newScope && newScope != null; if (popAfterwards) { var options = ctxt.CurrentContext.ContextDependentOptions; var applyOptions = ctxt.ScopedBlockIsInNodeHierarchy (m); ctxt.PushNewScope (newScope); if (applyOptions) ctxt.CurrentContext.ContextDependentOptions = options; } } var canResolveBase = ((ctxt.Options & ResolutionOptions.DontResolveBaseTypes) != ResolutionOptions.DontResolveBaseTypes) && stkC < 10 && (m.Type == null || m.Type.ToString(false) != m.Name); // To support resolving type parameters to concrete types if the context allows this, introduce all deduced parameters to the current context if (resultBase is DSymbol) ctxt.CurrentContext.IntroduceTemplateParameterTypes((DSymbol)resultBase); var importSymbolNode = m as ImportSymbolNode; var variable = m as DVariable; // Only import symbol aliases are allowed to search in the parse cache if (importSymbolNode != null) ret = HandleImportSymbolMatch (importSymbolNode,ctxt); else if (variable != null) { AbstractType bt = null; if (!(variable is EponymousTemplate)) { if (canResolveBase) { var bts = TypeDeclarationResolver.Resolve (variable.Type, ctxt); ctxt.CheckForSingleResult (bts, variable.Type); if (bts != null && bts.Length != 0) bt = bts [0]; // For auto variables, use the initializer to get its type else if (variable.Initializer != null) { bt = DResolver.StripMemberSymbols (Evaluation.EvaluateType (variable.Initializer, ctxt)); } // Check if inside an foreach statement header if (bt == null && ctxt.ScopedStatement != null) bt = GetForeachIteratorType (variable, ctxt); } // Note: Also works for aliases! In this case, we simply try to resolve the aliased type, otherwise the variable's base type ret = variable.IsAlias ? new AliasedType (variable, bt, typeBase as ISyntaxRegion) as MemberSymbol : new MemberSymbol (variable, bt, typeBase as ISyntaxRegion); } else ret = new EponymousTemplateType (variable as EponymousTemplate, GetInvisibleTypeParameters(variable, ctxt).AsReadOnly(), typeBase as ISyntaxRegion); } else if (m is DMethod) { ret = new MemberSymbol(m as DNode,canResolveBase ? GetMethodReturnType(m as DMethod, ctxt) : null, typeBase as ISyntaxRegion); } else if (m is DClassLike) ret = HandleClassLikeMatch (m as DClassLike, ctxt, typeBase, canResolveBase); else if (m is DModule) { var mod = (DModule)m; if (typeBase != null && typeBase.ToString() != mod.ModuleName) { var pack = ctxt.ParseCache.LookupPackage(typeBase.ToString()).FirstOrDefault(); if (pack != null) ret = new PackageSymbol(pack, typeBase as ISyntaxRegion); } else ret = new ModuleSymbol(m as DModule, typeBase as ISyntaxRegion); } else if (m is DEnum) ret = new EnumType((DEnum)m, typeBase as ISyntaxRegion); else if (m is TemplateParameter.Node) { //ResolveResult[] templateParameterType = null; //TODO: Resolve the specialization type //var templateParameterType = TemplateInstanceHandler.ResolveTypeSpecialization(tmp, ctxt); ret = new TemplateParameterSymbol((m as TemplateParameter.Node).TemplateParameter, null, typeBase as ISyntaxRegion); } else if(m is NamedTemplateMixinNode) { var tmxNode = m as NamedTemplateMixinNode; ret = new MemberSymbol(tmxNode, canResolveBase ? ResolveSingle(tmxNode.Type, ctxt) : null, typeBase as ISyntaxRegion); } if (popAfterwards) ctxt.Pop(); else if (resultBase is DSymbol) ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals((DSymbol)resultBase); if (stkC == 1) stackCalls.Remove(m); else stackCalls[m] = stkC-1; return ret; }
static AbstractType DeduceEponymousTemplate(EponymousTemplateType ept, ResolutionContext ctxt) { if (ept.Definition.Initializer == null) { ctxt.LogError (ept.Definition, "Can't deduce type from empty initializer!"); return null; } // Introduce the deduced params to the current resolution context ctxt.CurrentContext.IntroduceTemplateParameterTypes(ept); // Get actual overloads AbstractType deducedType = null; deducedType = new MemberSymbol (ept.Definition, Evaluation.EvaluateType (ept.Definition.Initializer, ctxt), null, ept.DeducedTypes); //ept; //Evaluation.EvaluateType (ept.Definition.Initializer, ctxt); // Undo context-related changes ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(ept); return deducedType; }
private static void GenerateMethodExpression(ScriptGenerator generator, MemberSymbol symbol, MethodExpression expression) { ScriptTextWriter writer = generator.Writer; if (expression.Method.SkipGeneration) { // If this method is to be skipped from generation, just generate the // left-hand-side object reference, and skip everything past it, including // the dot. GenerateExpression(generator, symbol, expression.ObjectReference); return; } if (expression.ObjectReference is BaseExpression) { Debug.Assert(expression.Method.IsExtension == false); writer.Write(((BaseExpression)expression.ObjectReference).EvaluatedType.FullGeneratedName); writer.Write(".prototype."); writer.Write(expression.Method.GeneratedName); writer.Write(".call("); writer.Write(generator.CurrentImplementation.ThisIdentifier); if ((expression.Parameters != null) && (expression.Parameters.Count != 0)) { writer.Write(", "); GenerateExpressionList(generator, symbol, expression.Parameters); } writer.Write(")"); } else { if (expression.Method.IsAliased) { writer.Write(expression.Method.Alias); writer.Write("("); if ((expression.Method.Visibility & MemberVisibility.Static) == 0) { GenerateExpression(generator, symbol, expression.ObjectReference); if ((expression.Parameters != null) && (expression.Parameters.Count != 0)) { writer.Write(", "); } } if ((expression.Parameters != null) && (expression.Parameters.Count != 0)) { GenerateExpressionList(generator, symbol, expression.Parameters); } writer.Write(")"); } else { if (expression.Method.IsExtension) { Debug.Assert(expression.Method.Parent.Type == SymbolType.Class); string extendee = ((ClassSymbol)expression.Method.Parent).Extendee; Debug.Assert(String.IsNullOrEmpty(extendee) == false); writer.Write(extendee); writer.Write("."); } else { GenerateExpression(generator, symbol, expression.ObjectReference); if (expression.Method.GeneratedName.Length != 0) { writer.Write("."); } } if (expression.Method.GeneratedName.Length != 0) { writer.Write(expression.Method.GeneratedName); } writer.Write("("); if (expression.Parameters != null) { GenerateExpressionList(generator, symbol, expression.Parameters); } writer.Write(")"); } } }
private static void GenerateLateBoundExpression(ScriptGenerator generator, MemberSymbol symbol, LateBoundExpression expression) { ScriptTextWriter writer = generator.Writer; string name = null; LiteralExpression literalNameExpression = expression.NameExpression as LiteralExpression; if ((literalNameExpression != null) && (literalNameExpression.Value is string)) { name = (string)literalNameExpression.Value; Debug.Assert(String.IsNullOrEmpty(name) == false); } if (expression.Operation == LateBoundOperation.DeleteField) { writer.Write("delete "); } if (expression.Operation == LateBoundOperation.GetScriptType) { writer.Write("typeof("); } else if (expression.Operation == LateBoundOperation.HasMethod) { writer.Write("(typeof("); } else if (expression.Operation == LateBoundOperation.HasField) { writer.Write("("); GenerateExpression(generator, symbol, expression.NameExpression); writer.Write(" in "); } if (expression.ObjectReference != null) { GenerateExpression(generator, symbol, expression.ObjectReference); } switch (expression.Operation) { case LateBoundOperation.InvokeMethod: if (Utility.IsValidIdentifier(name)) { if (expression.ObjectReference != null) { writer.Write("."); } writer.Write(name); } else { writer.Write("["); GenerateExpression(generator, symbol, expression.NameExpression); writer.Write("]"); } writer.Write("("); if (expression.Parameters.Count != 0) { GenerateExpressionList(generator, symbol, expression.Parameters); } writer.Write(")"); break; case LateBoundOperation.GetField: if (Utility.IsValidIdentifier(name)) { writer.Write("."); writer.Write(name); } else { writer.Write("["); GenerateExpression(generator, symbol, expression.NameExpression); writer.Write("]"); } break; case LateBoundOperation.SetField: if (Utility.IsValidIdentifier(name)) { writer.Write("."); writer.Write(name); } else { writer.Write("["); GenerateExpression(generator, symbol, expression.NameExpression); writer.Write("]"); } writer.Write(" = "); GenerateExpressionList(generator, symbol, expression.Parameters); break; case LateBoundOperation.DeleteField: if (Utility.IsValidIdentifier(name)) { writer.Write("."); writer.Write(name); } else { writer.Write("["); GenerateExpression(generator, symbol, expression.NameExpression); writer.Write("]"); } break; case LateBoundOperation.GetScriptType: writer.Write(")"); break; case LateBoundOperation.HasField: writer.Write(")"); break; case LateBoundOperation.HasMethod: if (Utility.IsValidIdentifier(name)) { if (expression.ObjectReference != null) { writer.Write("."); } writer.Write(name); } else { writer.Write("["); GenerateExpression(generator, symbol, expression.NameExpression); writer.Write("]"); } writer.Write(") === 'function')"); break; } }
private static void GenerateExpressionListAsNameValuePairs(ScriptGenerator generator, MemberSymbol symbol, ICollection <Expression> expressions) { Debug.Assert(expressions.Count % 2 == 0); ScriptTextWriter writer = generator.Writer; bool firstExpression = true; bool valueExpression = false; foreach (Expression expression in expressions) { if ((firstExpression == false) && (valueExpression == false)) { writer.Write(", "); } if (valueExpression) { writer.Write(": "); GenerateExpression(generator, symbol, expression); valueExpression = false; } else { Debug.Assert(expression.Type == ExpressionType.Literal); Debug.Assert(((LiteralExpression)expression).Value is string); string name = (string)((LiteralExpression)expression).Value; if (Utility.IsValidIdentifier(name)) { writer.Write(name); } else { writer.Write(Utility.QuoteString(name)); } valueExpression = true; } firstExpression = false; } }
private static void GenerateVariableDeclarationStatement(ScriptGenerator generator, MemberSymbol symbol, VariableDeclarationStatement statement) { ScriptTextWriter writer = generator.Writer; GenerateVariableDeclarations(generator, symbol, statement); writer.WriteLine(";"); }
void HandleMethod(DMethod dm, MemberSymbol alreadyResolvedMethod = null) { if (dm != null && dm.Parameters.Count > 0 && dm.Parameters[0].Type != null) { var loc = dm.Body != null ? dm.Body.Location : dm.Location; using (alreadyResolvedMethod != null ? ctxt.Push(alreadyResolvedMethod, loc) : ctxt.Push(dm, loc)) { var t = TypeDeclarationResolver.ResolveSingle(dm.Parameters[0].Type, ctxt); if (ResultComparer.IsImplicitlyConvertible(firstArgument, t, ctxt)) { var res = alreadyResolvedMethod ?? TypeDeclarationResolver.HandleNodeMatch(dm, ctxt, typeBase: sr); res.Tag(UfcsTag.Id, new UfcsTag { firstArgument = firstArgument }); matches.Add(res); } } } }
private void BuildMembers(TypeSymbol typeSymbol) { if (typeSymbol.Type == SymbolType.Delegate) { DelegateTypeNode delegateNode = (DelegateTypeNode)typeSymbol.ParseContext; TypeSymbol returnType = typeSymbol.SymbolSet.ResolveType(delegateNode.ReturnType, _symbolTable, typeSymbol); Debug.Assert(returnType != null); if (returnType != null) { MethodSymbol invokeMethod = new MethodSymbol("Invoke", typeSymbol, returnType, MemberVisibility.Public); invokeMethod.SetTransformedName(String.Empty); // Mark the method as abstract, as there is no actual implementation of the method // to be generated invokeMethod.SetImplementationState(SymbolImplementationFlags.Abstract); typeSymbol.AddMember(invokeMethod); } return; } CustomTypeNode typeNode = (CustomTypeNode)typeSymbol.ParseContext; foreach (MemberNode member in typeNode.Members) { MemberSymbol memberSymbol = null; switch (member.NodeType) { case ParseNodeType.FieldDeclaration: case ParseNodeType.ConstFieldDeclaration: memberSymbol = BuildField((FieldDeclarationNode)member, typeSymbol); break; case ParseNodeType.PropertyDeclaration: memberSymbol = BuildPropertyAsField((PropertyDeclarationNode)member, typeSymbol); if (memberSymbol == null) { memberSymbol = BuildProperty((PropertyDeclarationNode)member, typeSymbol); } break; case ParseNodeType.IndexerDeclaration: memberSymbol = BuildIndexer((IndexerDeclarationNode)member, typeSymbol); break; case ParseNodeType.ConstructorDeclaration: case ParseNodeType.MethodDeclaration: if ((member.Modifiers & Modifiers.Extern) != 0) { // Extern methods are there for defining overload signatures, so // we just skip them as far as metadata goes. The validator has // taken care of the requirements/constraints around use of extern methods. continue; } memberSymbol = BuildMethod((MethodDeclarationNode)member, typeSymbol); break; case ParseNodeType.EventDeclaration: memberSymbol = BuildEvent((EventDeclarationNode)member, typeSymbol); break; case ParseNodeType.EnumerationFieldDeclaration: memberSymbol = BuildEnumField((EnumerationFieldNode)member, typeSymbol); break; } if (memberSymbol != null) { memberSymbol.SetParseContext(member); if ((typeSymbol.IsApplicationType == false) && ((memberSymbol.Type == SymbolType.Constructor) || (typeSymbol.GetMember(memberSymbol.Name) != null))) { // If the type is an imported type, then it is allowed to contain // overloads, and we're simply going to ignore its existence, as long // as one overload has been added to the member table. continue; } typeSymbol.AddMember(memberSymbol); if ((typeSymbol.Type == SymbolType.Class) && (memberSymbol.Type == SymbolType.Event)) { EventSymbol eventSymbol = (EventSymbol)memberSymbol; if (eventSymbol.DefaultImplementation) { // Add a private field that will serve as the backing member // later on in the conversion (eg. in non-event expressions) MemberVisibility visibility = MemberVisibility.PrivateInstance; if ((eventSymbol.Visibility & MemberVisibility.Static) != 0) { visibility |= MemberVisibility.Static; } FieldSymbol fieldSymbol = new FieldSymbol("__" + Utility.CreateCamelCaseName(eventSymbol.Name), typeSymbol, eventSymbol.AssociatedType); fieldSymbol.SetVisibility(visibility); fieldSymbol.SetParseContext(((EventDeclarationNode)eventSymbol.ParseContext).Field); typeSymbol.AddMember(fieldSymbol); } } } } }
public static ISymbolValue Execute(MemberSymbol method, ISymbolValue[] arguments, AbstractSymbolValueProvider vp) { return new ErrorValue(new EvaluationException("CTFE is not implemented yet.")); }
static AbstractType DeduceEponymousTemplate(EponymousTemplateType ept, ResolutionContext ctxt) { if (ept.Definition.Initializer == null && ept.Definition.Type == null) { ctxt.LogError(ept.Definition, "Can't deduce type from empty initializer!"); return null; } // Introduce the deduced params to the current resolution context ctxt.CurrentContext.IntroduceTemplateParameterTypes(ept); // Get actual overloads AbstractType deducedType = null; var def = ept.Definition; deducedType = new MemberSymbol(def, def.Type != null ? TypeDeclarationResolver.ResolveSingle(def.Type, ctxt) : ExpressionTypeEvaluation.EvaluateType(def.Initializer, ctxt), null, ept.DeducedTypes); //ept; //ExpressionTypeEvaluation.EvaluateType (ept.Definition.Initializer, ctxt); deducedType.Tag = ept.Tag; // Currently requried for proper UFCS resolution - sustain ept's Tag // Undo context-related changes ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(ept); return deducedType; }
static void HandleDMethodOverload(ResolutionContext ctxt, bool eval, ISymbolValue baseValue, List <ISemantic> callArguments, bool returnBaseTypeOnly, List <AbstractType> argTypeFilteredOverloads, ref bool hasHandledUfcsResultBefore, MemberSymbol ms, ref AbstractType untemplatedMethod) { var dm = ms.Definition as DMethod; if (dm == null) { return; } ISemantic firstUfcsArg; bool isUfcs = UFCSResolver.IsUfcsResult(ms, out firstUfcsArg); // In the case of an ufcs, insert the first argument into the CallArguments list if (isUfcs && !hasHandledUfcsResultBefore) { callArguments.Insert(0, eval ? baseValue as ISemantic : firstUfcsArg); hasHandledUfcsResultBefore = true; } else if (!isUfcs && hasHandledUfcsResultBefore) // In the rare case of having a ufcs result occuring _after_ a normal member result, remove the initial arg again { callArguments.RemoveAt(0); hasHandledUfcsResultBefore = false; } if (dm.Parameters.Count == 0 && callArguments.Count > 0) { return; } var deducedTypeDict = new DeducedTypeDictionary(ms); var templateParamDeduction = new TemplateParameterDeduction(deducedTypeDict, ctxt); var back = ctxt.ScopedBlock; using (ctxt.Push(ms)) { if (ctxt.ScopedBlock != back) { ctxt.CurrentContext.DeducedTemplateParameters = deducedTypeDict; } bool add = true; int currentArg = 0; if (dm.Parameters.Count > 0 || callArguments.Count > 0) { bool hadDTuples = false; for (int i = 0; i < dm.Parameters.Count; i++) { var paramType = dm.Parameters[i].Type; // Handle the usage of tuples: Tuples may only be used as as-is, so not as an array, pointer or in a modified way.. if (paramType is IdentifierDeclaration && (hadDTuples |= TryHandleMethodArgumentTuple(ctxt, ref add, callArguments, dm, deducedTypeDict, i, ref currentArg))) { continue; } else if (currentArg < callArguments.Count) { if (!(add = templateParamDeduction.HandleDecl(null, paramType, callArguments[currentArg++]))) { break; } } else { // If there are more parameters than arguments given, check if the param has default values add = !(dm.Parameters[i] is DVariable) || (dm.Parameters[i] as DVariable).Initializer != null; // Assume that all further method parameters do have default values - and don't check further parameters break; } } // Too few args if (!hadDTuples && currentArg < callArguments.Count) { add = false; } } if (!add) { return; } // If type params were unassigned, try to take the defaults if (dm.TemplateParameters != null) { foreach (var tpar in dm.TemplateParameters) { if (deducedTypeDict[tpar] == null && !templateParamDeduction.Handle(tpar, null)) { return; } } } if (deducedTypeDict.AllParamatersSatisfied) { ms.DeducedTypes = deducedTypeDict.ToReadonly(); var bt = TypeDeclarationResolver.GetMethodReturnType(dm, ctxt) ?? ms.Base; if (eval || !returnBaseTypeOnly) { bt = new MemberSymbol(dm, bt, ms.DeclarationOrExpressionBase, ms.DeducedTypes) { Tag = ms.Tag } } ; if (dm.TemplateParameters == null || dm.TemplateParameters.Length == 0) { untemplatedMethod = bt; //ISSUE: Have another state that indicates an ambiguous non-templated method matching. } argTypeFilteredOverloads.Add(bt); } } }
public static void GenerateStatement(ScriptGenerator generator, MemberSymbol symbol, Statement statement) { switch (statement.Type) { case StatementType.Block: GenerateBlockStatement(generator, symbol, (BlockStatement)statement); break; case StatementType.Empty: break; case StatementType.VariableDeclaration: GenerateVariableDeclarationStatement(generator, symbol, (VariableDeclarationStatement)statement); break; case StatementType.Return: GenerateReturnStatement(generator, symbol, (ReturnStatement)statement); break; case StatementType.Expression: GenerateExpressionStatement(generator, symbol, (ExpressionStatement)statement); break; case StatementType.IfElse: GenerateIfElseStatement(generator, symbol, (IfElseStatement)statement); break; case StatementType.While: GenerateWhileStatement(generator, symbol, (WhileStatement)statement); break; case StatementType.For: GenerateForStatement(generator, symbol, (ForStatement)statement); break; case StatementType.ForIn: GenerateForInStatement(generator, symbol, (ForInStatement)statement); break; case StatementType.Switch: GenerateSwitchStatement(generator, symbol, (SwitchStatement)statement); break; case StatementType.Break: GenerateBreakStatement(generator, symbol, (BreakStatement)statement); break; case StatementType.Continue: GenerateContinueStatement(generator, symbol, (ContinueStatement)statement); break; case StatementType.Throw: GenerateThrowStatement(generator, symbol, (ThrowStatement)statement); break; case StatementType.TryCatchFinally: GenerateTryCatchFinallyStatement(generator, symbol, (TryCatchFinallyStatement)statement); break; case StatementType.Error: GenerateErrorStatement(generator, symbol, (ErrorStatement)statement); break; case StatementType.Using: GenerateUsingStatement(generator, symbol, (UsingStatement)statement); break; default: Debug.Fail("Unexpected statement type: " + statement.Type); break; } }
StatementSyntax GenerateTestStmtNullableValueTypeMember(MemberSymbol memberSymbol) { var memberName = memberSymbol.GetName(); return(IfStatement( BinaryExpression( SyntaxKind.LogicalAndExpression, BinaryExpression( SyntaxKind.NotEqualsExpression, IdentifierName(memberName), LiteralExpression(SyntaxKind.NullLiteralExpression) ), BinaryExpression( SyntaxKind.NotEqualsExpression, MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName("other"), IdentifierName(memberName) ), LiteralExpression(SyntaxKind.NullLiteralExpression) ) ), Block(SingletonList <StatementSyntax>( IfStatement( PrefixUnaryExpression( SyntaxKind.LogicalNotExpression, InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(memberName), IdentifierName("Value") ), IdentifierName("Equals") ) ).WithArgumentList(ArgumentList(SingletonSeparatedList <ArgumentSyntax>(Argument( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName("other"), IdentifierName(memberName) ), IdentifierName("Value") ) )))) ), ReturnStatement(LiteralExpression(SyntaxKind.FalseLiteralExpression)) ) )) ).WithElse(ElseClause( IfStatement( BinaryExpression( SyntaxKind.LogicalOrExpression, BinaryExpression( SyntaxKind.NotEqualsExpression, IdentifierName(memberName), LiteralExpression(SyntaxKind.NullLiteralExpression) ), BinaryExpression( SyntaxKind.NotEqualsExpression, MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName("other"), IdentifierName(memberName) ), LiteralExpression(SyntaxKind.NullLiteralExpression) ) ), ReturnStatement(LiteralExpression(SyntaxKind.FalseLiteralExpression)) ) ))); }
/// <summary> /// The variable's or method's base type will be resolved (if auto type, the intializer's type will be taken). /// A class' base class will be searched. /// etc.. /// </summary> public static AbstractType HandleNodeMatch( INode m, ResolverContextStack ctxt, AbstractType resultBase = null, object typeBase = null) { stackNum_HandleNodeMatch++; bool popAfterwards = m.Parent != ctxt.ScopedBlock && m.Parent is IBlockNode; if (popAfterwards) ctxt.PushNewScope((IBlockNode)m.Parent); //HACK: Really dirty stack overflow prevention via manually counting call depth var canResolveBaseGenerally = stackNum_HandleNodeMatch < 6; var DoResolveBaseType = canResolveBaseGenerally && !ctxt.Options.HasFlag(ResolutionOptions.DontResolveBaseClasses) && (m.Type == null || m.Type.ToString(false) != m.Name); AbstractType ret = null; // To support resolving type parameters to concrete types if the context allows this, introduce all deduced parameters to the current context if (canResolveBaseGenerally && resultBase is DSymbol) ctxt.CurrentContext.IntroduceTemplateParameterTypes((DSymbol)resultBase); // Only import symbol aliases are allowed to search in the parse cache if (m is ImportSymbolAlias) { var isa = (ImportSymbolAlias)m; if (isa.IsModuleAlias ? isa.Type != null : isa.Type.InnerDeclaration != null) { var mods = new List<DModule>(); var td=isa.IsModuleAlias ? isa.Type : isa.Type.InnerDeclaration; foreach (var mod in ctxt.ParseCache.LookupModuleName(td.ToString())) mods.Add(mod as DModule); if(mods.Count == 0) ctxt.LogError(new NothingFoundError(isa.Type)); else if(mods.Count > 1) { var m__=new List<ISemantic>(); foreach(var mod in mods) m__.Add(new ModuleSymbol(mod, isa.Type)); ctxt.LogError(new AmbiguityError(isa.Type,m__)); } var bt=mods.Count != 0 ? (AbstractType)new ModuleSymbol(mods[0], td) : null; //TODO: Is this correct behaviour? if (!isa.IsModuleAlias){ var furtherId = ResolveFurtherTypeIdentifier(isa.Type.ToString(false), new[]{ bt }, ctxt, isa.Type); ctxt.CheckForSingleResult(furtherId, isa.Type); if (furtherId != null && furtherId.Length != 0) bt = furtherId[0]; else bt = null; } ret = new AliasedType(isa, bt, isa.Type); } } else if (m is DVariable) { var v = (DVariable)m; AbstractType bt = null; if (DoResolveBaseType) { var bts = TypeDeclarationResolver.Resolve(v.Type, ctxt); if (bts != null && bts.Length != 0 && ctxt.CheckForSingleResult(bts, v.Type)) bt = bts[0]; // For auto variables, use the initializer to get its type else if (v.Initializer != null) bt = ExpressionSemantics.Evaluation.EvaluateType(v.Initializer, ctxt); // Check if inside an foreach statement header if (bt == null && ctxt.ScopedStatement != null) bt = GetForeachIteratorType(v, ctxt); } // Note: Also works for aliases! In this case, we simply try to resolve the aliased type, otherwise the variable's base type ret=v.IsAlias ? (DSymbol)new AliasedType(v, bt, typeBase as ISyntaxRegion) : new MemberSymbol(v, bt, typeBase as ISyntaxRegion); } else if (m is DMethod) { ret = new MemberSymbol((DNode)m, DoResolveBaseType ? GetMethodReturnType((DMethod)m, ctxt) : null , typeBase as ISyntaxRegion); } else if (m is DClassLike) { UserDefinedType udt = null; var dc=(DClassLike)m; switch (dc.ClassType) { case DTokens.Struct: udt = new StructType(dc, typeBase as ISyntaxRegion); break; case DTokens.Union: udt = new UnionType(dc, typeBase as ISyntaxRegion); break; case DTokens.Class: udt = new ClassType(dc, typeBase as ISyntaxRegion, null); break; case DTokens.Template: udt = new TemplateType(dc, typeBase as ISyntaxRegion); break; case DTokens.Interface: udt = new InterfaceType(dc, typeBase as ISyntaxRegion); break; default: ctxt.LogError(new ResolutionError(m, "Unknown type ("+DTokens.GetTokenString(dc.ClassType)+")")); break; } if (canResolveBaseGenerally && !ctxt.Options.HasFlag(ResolutionOptions.DontResolveBaseClasses)) ret = DResolver.ResolveBaseClasses(udt, ctxt); else ret = udt; } else if (m is IAbstractSyntaxTree) { var mod = (IAbstractSyntaxTree)m; if (typeBase != null && typeBase.ToString() != mod.ModuleName) { var pack = ctxt.ParseCache.LookupPackage(typeBase.ToString()).First(); if (pack != null) ret = new PackageSymbol(pack, typeBase as ISyntaxRegion); } else ret = new ModuleSymbol(m as DModule, typeBase as ISyntaxRegion); } else if (m is DEnum) ret = new EnumType((DEnum)m, typeBase as ISyntaxRegion); else if (m is TemplateParameterNode) { var tmp = ((TemplateParameterNode)m).TemplateParameter; //ResolveResult[] templateParameterType = null; //TODO: Resolve the specialization type //var templateParameterType = TemplateInstanceHandler.ResolveTypeSpecialization(tmp, ctxt); ret = new MemberSymbol((DNode)m, null, typeBase as ISyntaxRegion); } if (canResolveBaseGenerally && resultBase is DSymbol) ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals((DSymbol)resultBase); if (popAfterwards) ctxt.Pop(); stackNum_HandleNodeMatch--; return ret; }
public AssocArrayPointer(MemberSymbol assocArrayVariable, ISymbolValue accessedItemKey) : base(assocArrayVariable) { Key = accessedItemKey; }
private static void GenerateInlineScriptExpression(ScriptGenerator generator, MemberSymbol symbol, InlineScriptExpression expression) { ScriptTextWriter writer = generator.Writer; string script = expression.Script; ICollection <Expression> parameters = expression.Parameters; if (parameters != null) { Debug.Assert(parameters.Count != 0); string[] parameterScripts = new string[parameters.Count]; int i = 0; foreach (Expression parameterExpression in parameters) { StringWriter sw = new StringWriter(); try { writer.StartLocalWriting(sw); ExpressionGenerator.GenerateExpression(generator, symbol, parameterExpression); parameterScripts[i] = sw.ToString(); i++; } finally { writer.StopLocalWriting(); } } script = String.Format(CultureInfo.InvariantCulture, script, parameterScripts); } writer.Write(script); }
public StaticVariableValue(MemberSymbol staticPropertyResult) : base(staticPropertyResult) { }
private static void GenerateLocalExpression(ScriptGenerator generator, MemberSymbol symbol, LocalExpression expression) { ScriptTextWriter writer = generator.Writer; writer.Write(expression.Symbol.GeneratedName); }
public ArrayPointer(MemberSymbol arrayVariable, int accessedItem) : base(arrayVariable) { ItemNumber = accessedItem; }
private static void GenerateNewExpression(ScriptGenerator generator, MemberSymbol symbol, NewExpression expression) { ScriptTextWriter writer = generator.Writer; if (expression.IsSpecificType) { string type = expression.AssociatedType.FullGeneratedName; if (type.Equals("Array")) { if (expression.Parameters == null) { writer.Write("[]"); } else if ((expression.Parameters.Count == 1) && (expression.Parameters[0].EvaluatedType == symbol.SymbolSet.ResolveIntrinsicType(IntrinsicType.Integer))) { writer.Write("new Array("); GenerateExpression(generator, symbol, expression.Parameters[0]); writer.Write(")"); } else { writer.Write("["); GenerateExpressionList(generator, symbol, expression.Parameters); writer.Write("]"); } return; } else if (type.Equals("Object")) { if (expression.Parameters == null) { writer.Write("{}"); } else { writer.Write("{ "); GenerateExpressionListAsNameValuePairs(generator, symbol, expression.Parameters); writer.Write(" }"); } return; } else if (type.Equals("Tuple")) { if ((expression.Parameters == null) || (expression.Parameters.Count == 0)) { writer.Write("{ }"); } else { writer.Write("{ "); for (int i = 0; i < expression.Parameters.Count; i++) { if (i != 0) { writer.Write(", "); } writer.Write("item"); writer.Write(i + 1); writer.Write(": "); GenerateExpression(generator, symbol, expression.Parameters[i]); } writer.Write(" }"); } return; } else if (expression.AssociatedType.Type == SymbolType.Record) { if (expression.AssociatedType.IsApplicationType && ((RecordSymbol)expression.AssociatedType).Constructor == null) { writer.Write("{ }"); return; } writer.Write(expression.AssociatedType.FullGeneratedName); writer.Write("("); if (expression.Parameters != null) { GenerateExpressionList(generator, symbol, expression.Parameters); } writer.Write(")"); return; } } writer.Write("new "); if (expression.IsSpecificType) { writer.Write(expression.AssociatedType.FullGeneratedName); } else { GenerateExpression(generator, symbol, expression.TypeExpression); } writer.Write("("); if (expression.Parameters != null) { GenerateExpressionList(generator, symbol, expression.Parameters); } writer.Write(")"); }
public VariableValue(MemberSymbol mr) : base(mr.Base) { this.Member = mr; this.Variable = mr.Definition as DVariable; }
public static ISymbolValue Execute(MemberSymbol method, Dictionary<DVariable, ISymbolValue> arguments, AbstractSymbolValueProvider vp) { var dm = method.Definition as DMethod; var eval = new FunctionEvaluation(method,vp,arguments); var ctxt = vp.ResolutionContext; ctxt.PushNewScope(dm, dm.Body); try { dm.Body.Accept(eval); } catch (CtfeException ex) { vp.LogError(dm, "Can't execute function at precompile time: " + ex.Message); } var ret = Evaluation.GetVariableContents(eval.returnedValue, eval.vp); ctxt.Pop(); return ret; //return new ErrorValue(new EvaluationException("CTFE is not implemented yet.")); }
void HandleMethod(DMethod dm, MemberSymbol alreadyResolvedMethod = null) { if (dm != null && dm.Parameters.Count > 0 && dm.Parameters[0].Type != null) { var pop = ctxt.ScopedBlock != dm; if (pop) ctxt.PushNewScope (dm); var t = TypeDeclarationResolver.ResolveSingle (dm.Parameters [0].Type, ctxt); if (ResultComparer.IsImplicitlyConvertible (firstArgument, t, ctxt)) { var res = alreadyResolvedMethod ?? new MemberSymbol (dm, null, sr); res.Tag = new UfcsTag{ firstArgument=firstArgument }; matches.Add (res); } if (pop) ctxt.Pop (); } }
public AbstractType Visit(NewExpression nex) { // http://www.d-programming-language.org/expression.html#NewExpression AbstractType[] possibleTypes; if (nex.Type is IdentifierDeclaration) { possibleTypes = TypeDeclarationResolver.Resolve((IdentifierDeclaration)nex.Type, ctxt, filterForTemplateArgs: false); } else { possibleTypes = TypeDeclarationResolver.Resolve(nex.Type, ctxt); } var ctors = new Dictionary <DMethod, TemplateIntermediateType>(); if (possibleTypes == null) { return(null); } foreach (var t in possibleTypes) { var ct = t as TemplateIntermediateType; if (ct != null && !ct.Definition.ContainsAttribute(DTokens.Abstract)) { foreach (var ctor in GetConstructors(ct)) { // Omit all ctors that won't return the adequate if (ct.Modifier != 0) { if (!ctor.ContainsAttribute(ct.Modifier, DTokens.Pure)) { continue; } } else if (ctor.Attributes != null && ctor.Attributes.Count != 0) { bool skip = false; foreach (var attr in ctor.Attributes) { var mod = attr as Modifier; if (mod != null) { switch (mod.Token) { case DTokens.Const: case DTokens.Immutable: case DTokens.Shared: case DTokens.Nothrow: // ? // not DTokens.Pure due to some mystical reasons skip = true; break; } if (skip) { break; } } } if (skip) { continue; } } ctors.Add(ctor, ct); } } else if (t is AssocArrayType) { t.NonStaticAccess = true; return(AmbiguousType.Get(possibleTypes)); } } if (ctors.Count == 0) { return(new UnknownType(nex)); } // HACK: Return the base types immediately if (TryReturnMethodReturnType) { var ret = ctors.First().Value; // AmbiguousType.Get(ctors.Values); if (ret != null) { ret.NonStaticAccess = true; } return(ret); } MemberSymbol finalCtor = null; //TODO: Determine argument types and filter out ctor overloads. var kvFirst = ctors.First(); finalCtor = new MemberSymbol(kvFirst.Key, kvFirst.Value, nex); if (finalCtor != null) { return(TryPretendMethodExecution(finalCtor, nex)); } var resolvedCtors = new List <AbstractType>(); foreach (var kv in ctors) { resolvedCtors.Add(new MemberSymbol(kv.Key, kv.Value, nex)); } return(TryPretendMethodExecution(AmbiguousType.Get(resolvedCtors, nex), nex)); }
private static void GenerateThisExpression(ScriptGenerator generator, MemberSymbol symbol, ThisExpression expression) { ScriptTextWriter writer = generator.Writer; writer.Write(generator.CurrentImplementation.ThisIdentifier); }
private static void GenerateBinaryExpression(ScriptGenerator generator, MemberSymbol symbol, BinaryExpression expression) { ScriptTextWriter writer = generator.Writer; if (expression.Operator == Operator.Equals) { if (expression.LeftOperand is PropertyExpression propExpression) { Debug.Assert(propExpression.Type == ExpressionType.PropertySet); if (propExpression.ObjectReference is BaseExpression) { ClassSymbol classSymbol = (ClassSymbol)symbol.Parent; writer.Write($"{DSharpStringResources.ScriptExportMember("baseProperty")}("); writer.Write(classSymbol.FullGeneratedName); writer.Write(", '"); writer.Write(propExpression.Property.GeneratedName); writer.Write("').set.call("); writer.Write(generator.CurrentImplementation.ThisIdentifier); writer.Write(", "); GenerateExpression(generator, symbol, expression.RightOperand); writer.Write(")"); } else { GenerateExpression(generator, symbol, propExpression.ObjectReference); writer.Write("."); writer.Write(propExpression.Property.GeneratedName); writer.Write(" = "); GenerateExpression(generator, symbol, expression.RightOperand); } propExpression.Property.IncrementReferenceCount(); return; } if (expression.LeftOperand is IndexerExpression indexExpression) { IndexerSymbol indexerSymbol = indexExpression.Indexer; if (!indexerSymbol.UseScriptIndexer) { Debug.Assert(indexExpression.Type == ExpressionType.Indexer); if (indexExpression.ObjectReference is BaseExpression objectReference) { writer.Write(objectReference.EvaluatedType.FullGeneratedName); writer.Write(".prototype.set_"); writer.Write(indexerSymbol.GeneratedName); writer.Write(".call("); writer.Write(generator.CurrentImplementation.ThisIdentifier); writer.Write(", "); GenerateExpressionList(generator, symbol, indexExpression.Indices); writer.Write(", "); GenerateExpression(generator, symbol, expression.RightOperand); writer.Write(")"); } else { GenerateExpression(generator, symbol, indexExpression.ObjectReference); writer.Write(".set_"); writer.Write(indexerSymbol.GeneratedName); writer.Write("("); GenerateExpressionList(generator, symbol, indexExpression.Indices); writer.Write(", "); GenerateExpression(generator, symbol, expression.RightOperand); writer.Write(")"); } indexExpression.Indexer.IncrementReferenceCount(); return; } else if (indexerSymbol.Parent is TypeSymbol typeSymbol && !typeSymbol.IsNativeArray) { writer.Write($"ss.setItem("); GenerateExpression(generator, symbol, indexExpression.ObjectReference); writer.Write(", "); GenerateExpressionList(generator, symbol, indexExpression.Indices); writer.Write(", "); GenerateExpression(generator, symbol, expression.RightOperand); writer.Write(")"); return; } } } else if (expression.Operator == Operator.PlusEquals || expression.Operator == Operator.MinusEquals || expression.Operator == Operator.MultiplyEquals || expression.Operator == Operator.DivideEquals || expression.Operator == Operator.ModEquals || expression.Operator == Operator.BitwiseOrEquals || expression.Operator == Operator.BitwiseAndEquals || expression.Operator == Operator.BitwiseXorEquals || expression.Operator == Operator.ShiftLeftEquals || expression.Operator == Operator.ShiftRightEquals || expression.Operator == Operator.UnsignedShiftRightEquals) { if (expression.LeftOperand is PropertyExpression propExpression) { Debug.Assert(propExpression.Type == ExpressionType.PropertyGet); GenerateExpression(generator, symbol, propExpression.ObjectReference); writer.Write("."); writer.Write(propExpression.Property.GeneratedName); writer.Write(" = "); GenerateExpression(generator, symbol, propExpression.ObjectReference); writer.Write(OperatorConverter.OperatorToString(expression.Operator - 1)); GenerateExpression(generator, symbol, expression.RightOperand); propExpression.Property.IncrementReferenceCount(); return; } } else if (expression.Operator == Operator.Is || expression.Operator == Operator.As) { TypeExpression typeExpression = expression.RightOperand as TypeExpression; Debug.Assert(typeExpression != null); writer.Write(DSharpStringResources.ScriptExportMember(string.Empty)); if (expression.Operator == Operator.Is) { writer.Write("canCast("); } else { writer.Write("safeCast("); } GenerateExpression(generator, symbol, expression.LeftOperand); writer.Write(", "); writer.Write(typeExpression.AssociatedType.FullGeneratedName); writer.Write(")"); typeExpression.AssociatedType.IncrementReferenceCount(); return; } else if (expression.Operator == Operator.EqualEqualEqual || expression.Operator == Operator.NotEqualEqual) { if (expression.RightOperand is LiteralExpression literalExpression) { // Optimize generated script to perform loose equality checks for false-y values // (null, false, 0, empty string) // TODO: This should really be happening at compilation time, rather than generation // time. Because this is happening at generation time, we get something like // if (!!x) when if(x) would suffice just so we can get // foo(!!x) where foo is a method expecting a boolean. // Doing this at compilation time would allow handling if scenarios specially. bool optimizable = false; bool checkForFalse = false; if (literalExpression.Value is bool compareValue) { optimizable = true; if (compareValue && expression.Operator == Operator.NotEqualEqual || !compareValue && expression.Operator == Operator.EqualEqualEqual) { checkForFalse = true; } } else if (literalExpression.Value is int i && i == 0) { optimizable = true; checkForFalse = expression.Operator == Operator.EqualEqualEqual; } else if (literalExpression.Value is string s && s == string.Empty) { optimizable = true; checkForFalse = expression.Operator == Operator.EqualEqualEqual; } if (optimizable) { bool parenthesize = false; writer.Write(checkForFalse ? "!" : "!!"); if (expression.LeftOperand.Parenthesized == false && (expression.LeftOperand.Type == ExpressionType.Binary || expression.LeftOperand.Type == ExpressionType.Conditional || expression.LeftOperand.Type == ExpressionType.InlineScript)) { parenthesize = true; writer.Write("("); } GenerateExpression(generator, symbol, expression.LeftOperand); if (parenthesize) { writer.Write(")"); } return; } } }
private static void GenerateTypeExpression(ScriptGenerator generator, MemberSymbol symbol, TypeExpression expression) { ScriptTextWriter writer = generator.Writer; writer.Write(expression.AssociatedType.FullGeneratedName); }
private static void GenerateForInStatement(ScriptGenerator generator, MemberSymbol symbol, ForInStatement statement) { ScriptTextWriter writer = generator.Writer; TypeSymbol evaluatedType = statement.CollectionExpression.EvaluatedType; if (statement.IsDictionaryEnumeration) { if (statement.DictionaryVariable != null) { writer.Write("var "); writer.Write(statement.DictionaryVariable.GeneratedName); writer.Write(" = "); ExpressionGenerator.GenerateExpression(generator, symbol, statement.CollectionExpression); writer.Write(";"); writer.WriteLine(); } writer.Write("for (var "); writer.Write(statement.LoopVariable.GeneratedName); writer.Write(" in "); if (statement.DictionaryVariable != null) { writer.Write(statement.DictionaryVariable.GeneratedName); } else { ExpressionGenerator.GenerateExpression(generator, symbol, statement.CollectionExpression); } writer.WriteLine(") {"); writer.Indent++; writer.Write("var "); writer.Write(statement.ItemVariable.GeneratedName); writer.Write(" = { key: "); writer.Write(statement.LoopVariable.GeneratedName); writer.Write(", value: "); if (statement.DictionaryVariable != null) { writer.Write(statement.DictionaryVariable.GeneratedName); } else { ExpressionGenerator.GenerateExpression(generator, symbol, statement.CollectionExpression); } writer.Write("["); writer.Write(statement.LoopVariable.GeneratedName); writer.WriteLine("] };"); GenerateStatement(generator, symbol, statement.Body); writer.Indent--; writer.WriteLine("}"); } else if (evaluatedType.IsNativeArray || evaluatedType.IsListType()) { string dataSourceVariableName = statement.LoopVariable.GeneratedName; string indexVariableName = dataSourceVariableName + "_index"; // var $$ = ({CollectionExpression}); writer.Write("var " + dataSourceVariableName + " = ("); ExpressionGenerator.GenerateExpression(generator, symbol, statement.CollectionExpression); writer.WriteLine(");"); // for(var items_index = 0; items_index < items.length; ++items_index) { writer.WriteLine("for(var " + indexVariableName + " = 0; " + indexVariableName + " < " + dataSourceVariableName + ".length; ++" + indexVariableName + ") {"); ++writer.Indent; if (evaluatedType.IsNativeArray) { // var i = items[items_index]; writer.WriteLine("var " + statement.ItemVariable.GeneratedName + " = " + dataSourceVariableName + "[" + indexVariableName + "];"); } else { // var i = ss.getItem(items, items_index); writer.WriteLine("var " + statement.ItemVariable.GeneratedName + " = ss.getItem(" + dataSourceVariableName + ", " + indexVariableName + ");"); } GenerateStatement(generator, symbol, statement.Body); --writer.Indent; writer.WriteLine("}"); } else { writer.Write("var "); writer.Write(statement.LoopVariable.GeneratedName); writer.Write(" = "); writer.Write($"{DSharpStringResources.ScriptExportMember("enumerate")}("); ExpressionGenerator.GenerateExpression(generator, symbol, statement.CollectionExpression); writer.Write(");"); writer.WriteLine(); writer.Write("while ("); writer.Write(statement.LoopVariable.GeneratedName); writer.WriteLine(".moveNext()) {"); writer.Indent++; writer.Write("var "); writer.Write(statement.ItemVariable.GeneratedName); writer.Write(" = "); writer.Write(statement.LoopVariable.GeneratedName); writer.Write(".current;"); writer.WriteLine(); GenerateStatement(generator, symbol, statement.Body); writer.Indent--; writer.Write("}"); writer.WriteLine(); } }
private static void GenerateBaseInitializerExpression(ScriptGenerator generator, MemberSymbol symbol, BaseInitializerExpression expression) { ScriptTextWriter writer = generator.Writer; Debug.Assert(symbol.Parent is ClassSymbol); ClassSymbol baseClass = ((ClassSymbol)symbol.Parent).BaseClass; Debug.Assert(baseClass != null); writer.Write(baseClass.FullGeneratedName); writer.Write(".call(this"); if (expression.Parameters != null) { writer.Write(", "); GenerateExpressionList(generator, symbol, expression.Parameters); } writer.Write(")"); }
private static void GenerateTryCatchFinallyStatement(ScriptGenerator generator, MemberSymbol symbol, TryCatchFinallyStatement statement) { ScriptTextWriter writer = generator.Writer; writer.WriteLine("try {"); writer.Indent++; GenerateStatement(generator, symbol, statement.Body); writer.Indent--; writer.WriteLine("}"); if (statement.Catch != null) { writer.Write("catch ("); writer.Write(statement.ExceptionVariable.GeneratedName); writer.WriteLine(") {"); writer.Indent++; GenerateStatement(generator, symbol, statement.Catch); writer.Indent--; writer.WriteLine("}"); } if (statement.Finally != null) { writer.WriteLine("finally {"); writer.Indent++; GenerateStatement(generator, symbol, statement.Finally); writer.Indent--; writer.WriteLine("}"); } }
private static void GenerateEnumerationFieldExpression(ScriptGenerator generator, MemberSymbol symbol, EnumerationFieldExpression expression) { ScriptTextWriter writer = generator.Writer; ExpressionGenerator.GenerateExpression(generator, symbol, expression.ObjectReference); writer.Write("."); writer.Write(expression.Field.GeneratedName); }
private bool MemberIsNotAliased(MemberSymbol arg) { return(!arg.GeneratedName.Contains('.')); }
public static void GenerateExpression(ScriptGenerator generator, MemberSymbol symbol, Expression expression) { ScriptTextWriter writer = generator.Writer; if (expression.Parenthesized) { writer.Write("("); } switch (expression.Type) { case ExpressionType.Literal: GenerateLiteralExpression(generator, symbol, (LiteralExpression)expression); break; case ExpressionType.Local: GenerateLocalExpression(generator, symbol, (LocalExpression)expression); break; case ExpressionType.Member: Debug.Fail("MemberExpression missed from conversion to higher level expression."); break; case ExpressionType.Field: GenerateFieldExpression(generator, symbol, (FieldExpression)expression); break; case ExpressionType.EnumerationField: GenerateEnumerationFieldExpression(generator, symbol, (EnumerationFieldExpression)expression); break; case ExpressionType.PropertyGet: GeneratePropertyExpression(generator, symbol, (PropertyExpression)expression); break; case ExpressionType.PropertySet: Debug.Fail("PropertyExpression(set) should be covered as part of BinaryExpression logic."); break; case ExpressionType.MethodInvoke: case ExpressionType.DelegateInvoke: GenerateMethodExpression(generator, symbol, (MethodExpression)expression); break; case ExpressionType.BaseInitializer: GenerateBaseInitializerExpression(generator, symbol, (BaseInitializerExpression)expression); break; case ExpressionType.EventAdd: case ExpressionType.EventRemove: GenerateEventExpression(generator, symbol, (EventExpression)expression); break; case ExpressionType.Indexer: GenerateIndexerExpression(generator, symbol, (IndexerExpression)expression); break; case ExpressionType.This: GenerateThisExpression(generator, symbol, (ThisExpression)expression); break; case ExpressionType.Base: Debug.Fail("BaseExpression not handled by container expression."); break; case ExpressionType.New: GenerateNewExpression(generator, symbol, (NewExpression)expression); break; case ExpressionType.Unary: GenerateUnaryExpression(generator, symbol, (UnaryExpression)expression); break; case ExpressionType.Binary: GenerateBinaryExpression(generator, symbol, (BinaryExpression)expression); break; case ExpressionType.Conditional: GenerateConditionalExpression(generator, symbol, (ConditionalExpression)expression); break; case ExpressionType.Type: GenerateTypeExpression(generator, symbol, (TypeExpression)expression); break; case ExpressionType.Delegate: GenerateDelegateExpression(generator, symbol, (DelegateExpression)expression); break; case ExpressionType.LateBound: GenerateLateBoundExpression(generator, symbol, (LateBoundExpression)expression); break; case ExpressionType.InlineScript: GenerateInlineScriptExpression(generator, symbol, (InlineScriptExpression)expression); break; case ExpressionType.NewDelegate: GenerateExpression(generator, symbol, ((NewDelegateExpression)expression).TypeExpression); break; default: Debug.Fail("Unexpected expression type: " + expression.Type); break; } if (expression.Parenthesized) { writer.Write(")"); } }