internal static ClassDefinition DoClassLookup(TopLevelConstruct currentContainer, Token nameToken, string name, bool failSilently) { TopLevelConstruct ex = currentContainer.FileScope.FileScopeEntityLookup.DoEntityLookup(name, currentContainer); if (ex == null) { if (failSilently) { return(null); } string message = "No class named '" + name + "' was found."; if (name.Contains(".")) { message += " Did you forget to import a library?"; } throw new ParserException(nameToken, message); } if (ex is ClassDefinition) { return((ClassDefinition)ex); } // Still throw an exception if the found item is not a class. This is used by code to check if // something is a valid variable name or a class name. Colliding with something else is bad. throw new ParserException(nameToken, "This is not a class."); }
public string[] GetWrappingNamespaceIncrements(Locale locale) { if (!this.localNamespaceByLocale.ContainsKey(locale)) { TopLevelConstruct ownerWalker = this.Owner; while (ownerWalker != null && !(ownerWalker is Namespace)) { ownerWalker = ownerWalker.Owner; } string ns = ownerWalker == null ? "" : ownerWalker.GetFullyQualifiedLocalizedName(locale); if (!TopLevelConstruct.namespacePartCache.ContainsKey(ns)) { if (ns.Length == 0) { TopLevelConstruct.namespacePartCache[""] = new string[0]; } else { string[] parts = ns.Split('.'); for (int i = 1; i < parts.Length; ++i) { parts[i] = parts[i - 1] + "." + parts[i]; } Array.Reverse(parts); TopLevelConstruct.namespacePartCache[ns] = parts; } } this.localNamespaceByLocale[locale] = TopLevelConstruct.namespacePartCache[ns]; } return(this.localNamespaceByLocale[locale]); }
public NamespaceReference(Token firstToken, TopLevelConstruct owner, NamespaceReferenceTemplate nsRef) : base(firstToken, owner) { this.Template = nsRef; this.OriginalNamespace = nsRef.OriginalNamespace; this.Name = nsRef.Name; }
public ClassDefinition( Token classToken, Token nameToken, IList <Token> subclassTokens, IList <string> subclassNames, TopLevelConstruct owner, LibraryMetadata library, Token staticToken, Token finalToken, FileScope fileScope, AnnotationCollection annotations) : base(classToken, owner, fileScope) { this.Library = library; this.ClassID = ClassDefinition.classIdAlloc++; this.NameToken = nameToken; this.BaseClassTokens = subclassTokens.ToArray(); this.BaseClassDeclarations = subclassNames.ToArray(); this.StaticToken = staticToken; this.FinalToken = finalToken; this.annotations = annotations; if (staticToken != null && this.BaseClassTokens.Length > 0) { throw new ParserException(staticToken, "Class cannot be static and have base classes or interfaces."); } }
public DotStep(Expression root, Token dotToken, Token stepToken, TopLevelConstruct owner) : base(root.FirstToken, owner) { this.Root = root; this.DotToken = dotToken; this.StepToken = stepToken; }
public Namespace( Token namespaceToken, string name, TopLevelConstruct owner, LibraryMetadata library, FileScope fileScope, AnnotationCollection annotations) : base(namespaceToken, owner, fileScope) { this.Library = library; this.DefaultName = name; this.FullyQualifiedDefaultName = owner == null ? name : (((Namespace)owner).FullyQualifiedDefaultName + "." + name); this.FullyQualifiedDefaultNameSegments = this.FullyQualifiedDefaultName.Split('.'); this.DefaultNameSegments = this.DefaultName.Split('.'); this.NamesByLocale = annotations.GetNamesByLocale(this.DefaultNameSegments.Length) .ToDictionary(kvp => kvp.Key, kvp => kvp.Value.Split('.')); Locale defaultLocale = fileScope.CompilationScope.Locale; if (!this.NamesByLocale.ContainsKey(defaultLocale)) { this.NamesByLocale[defaultLocale] = this.DefaultName.Split('.'); } this.NestDepth = this.FullyQualifiedDefaultNameSegments.Length - this.DefaultNameSegments.Length; }
public BracketIndex(Expression root, Token bracketToken, Expression index, TopLevelConstruct owner) : base(root.FirstToken, owner) { this.Root = root; this.BracketToken = bracketToken; this.Index = index; }
public BinaryOpChain(Expression left, Token op, Expression right, TopLevelConstruct owner) : base(left.FirstToken, owner) { this.Left = left; this.Right = right; this.Op = op; }
public Executable(Token firstToken, TopLevelConstruct owner) : base(firstToken, owner) { if (owner == null) { throw new Exception(); // This should never happen. } }
public ConstructorDefinition(TopLevelConstruct owner, AnnotationCollection annotations) : base(null, owner, owner.FileScope) { this.IsDefault = true; this.Code = new Executable[0]; this.ArgNames = new Token[0]; this.DefaultValues = new Expression[0]; this.BaseArgs = new Expression[0]; this.MaxArgCount = 0; this.MinArgCount = 0; this.Annotations = annotations; }
public ConstStatement( Token constToken, Token nameToken, TopLevelConstruct owner, LibraryMetadata library, FileScope fileScope, AnnotationCollection annotations) : base(constToken, owner, fileScope) { this.Library = library; this.NameToken = nameToken; this.Name = nameToken.Value; this.annotations = annotations; }
public EnumDefinition( Token enumToken, Token nameToken, TopLevelConstruct owner, LibraryMetadata library, FileScope fileScope, AnnotationCollection annotations) : base(enumToken, owner, fileScope) { this.Library = library; this.NameToken = nameToken; this.Name = nameToken.Value; this.annotations = annotations; }
public CoreFunctionInvocation(Token firstToken, Expression[] originalArgs, TopLevelConstruct owner) : base(firstToken, owner) { if (originalArgs.Length == 0 || !(originalArgs[0] is StringConstant)) { throw new ParserException(firstToken, "$$$ invocations must include a string constant containing the function name."); } this.FunctionId = CoreFunctionIDHelper.GetId((StringConstant)originalArgs[0]); List <Expression> args = new List <Expression>(originalArgs); args.RemoveAt(0); this.Args = args.ToArray(); }
public FunctionDefinition( Token functionToken, LibraryMetadata library, TopLevelConstruct nullableOwner, bool isStaticMethod, Token nameToken, AnnotationCollection annotations, FileScope fileScope) : base(functionToken, nullableOwner, fileScope) { this.Library = library; this.IsStaticMethod = isStaticMethod; this.NameToken = nameToken; this.Annotations = annotations; this.MemberID = -1; }
// pardon the double-plurals for the jaggy 2D arrays public TryStatement( Token tryToken, IList <Executable> tryBlock, List <Token> catchTokens, List <Token> exceptionVariableTokens, List <Token[]> catchBlockTypeTokenses, // tricksy tokenses List <string[]> catchBlockTypeses, List <Executable[]> catchBlockExecutableses, Token finallyToken, IList <Executable> finallyBlock, TopLevelConstruct owner) : base(tryToken, owner) { this.TryToken = tryToken; this.TryBlock = tryBlock.ToArray(); int catchBlockCount = catchTokens.Count; // individual catch-related inputs are trusted to all have same length this.CatchBlocks = new CatchBlock[catchBlockCount]; for (int i = 0; i < catchBlockCount; ++i) { Token catchToken = catchTokens[i]; Token variableName = exceptionVariableTokens[i]; Token[] catchBlockTypeTokens = catchBlockTypeTokenses[i]; string[] catchBlockTypes = catchBlockTypeses[i]; Executable[] catchBlockExecutables = catchBlockExecutableses[i]; this.CatchBlocks[i] = new CatchBlock() { CatchToken = catchToken, Code = catchBlockExecutables, ExceptionVariableToken = variableName, Types = catchBlockTypes, TypeTokens = catchBlockTypeTokens, VariableLocalScopeId = -1, }; } this.FinallyToken = finallyToken; this.FinallyBlock = finallyBlock == null ? new Executable[0] : finallyBlock.ToArray(); if (this.CatchBlocks.Length == 0 && this.FinallyBlock == null) { throw new ParserException(this.TryToken, "Cannot have a try block without a catch or finally block."); } }
internal override void PerformLocalIdAllocation(ParserContext parser, VariableIdAllocator varIds, VariableIdAllocPhase phase) { if ((phase & VariableIdAllocPhase.ALLOC) != 0) { this.LocalScopeId = varIds.GetVarId(this.FirstToken); if (this.LocalScopeId == -1) { string name = this.FirstToken.Value; if (parser.LibraryManager.IsValidLibraryNameFromLocale(this.Owner.FileScope.CompilationScope.Locale, name)) { throw new ParserException(this.FirstToken, "'" + name + "' is referenced but not imported in this file."); } TopLevelConstruct owner = this.Owner; while (owner != null && !(owner is ClassDefinition)) { owner = owner.Owner; } if (owner != null) { ClassDefinition cd = (ClassDefinition)owner; foreach (FieldDeclaration fd in cd.Fields) { if (fd.NameToken.Value == name) { string message = "'" + name + "' is used like a local variable but it is " + (fd.IsStaticField ? "a static" : "an instance") + " field."; message += " Did you mean '" + (fd.IsStaticField ? cd.NameToken.Value : "this") + "." + name + "' instead of '" + name + "'?"; throw new ParserException(this.FirstToken, message); } } } // TODO: But if it's being called like a function then... // - give a better error message "function 'foo' is not defined" // - give an even better error message when there's a class or instance function with the same name // e.g. "'foo' is a static function and must be invoked with the class name: FooClass.foo(...) // - if there's a method, suggest using "this." // - if the variable name matches a library that is available, suggest it as a missing import. throw new ParserException(this.FirstToken, "The variable '" + name + "' is used but is never assigned to."); } } }
public void ResolveBaseClasses() { List <ClassDefinition> baseClasses = new List <ClassDefinition>(); List <Token> baseClassesTokens = new List <Token>(); for (int i = 0; i < this.BaseClassDeclarations.Length; ++i) { string value = this.BaseClassDeclarations[i]; Token token = this.BaseClassTokens[i]; TopLevelConstruct baseClassInstance = this.FileScope.FileScopeEntityLookup.DoEntityLookup(value, this); if (baseClassInstance == null) { throw new ParserException(token, "No class named '" + token.Value + "' was found."); } if (baseClassInstance is ClassDefinition) { baseClasses.Add((ClassDefinition)baseClassInstance); baseClassesTokens.Add(token); } // TODO: else if (baseClassInstance is InterfaceDefinition) { ... } else { throw new ParserException(token, "This is not a class."); } } if (baseClasses.Count > 1) { throw new ParserException(baseClassesTokens[1], "Multiple base classes found. Did you mean to use an interface?"); } if (baseClasses.Count == 1) { this.BaseClass = baseClasses[0]; } }
public ConstructorDefinition( Token constructorToken, IList <Token> args, IList <Expression> defaultValues, IList <Expression> baseArgs, IList <Executable> code, Token baseToken, AnnotationCollection annotations, TopLevelConstruct owner) : base(constructorToken, owner, owner.FileScope) { this.IsDefault = false; this.ArgNames = args.ToArray(); this.DefaultValues = defaultValues.ToArray(); this.BaseArgs = baseArgs.ToArray(); this.Code = code.ToArray(); this.BaseToken = baseToken; this.Annotations = annotations; TODO.VerifyDefaultArgumentsAreAtTheEnd(); this.MaxArgCount = this.ArgNames.Length; int minArgCount = 0; for (int i = 0; i < this.ArgNames.Length; ++i) { if (this.DefaultValues[i] == null) { minArgCount++; } else { break; } } this.MinArgCount = minArgCount; }
public BooleanCombination(IList <Expression> expressions, IList <Token> ops, TopLevelConstruct owner) : base(expressions[0].FirstToken, owner) { this.Expressions = expressions.ToArray(); this.Ops = ops.ToArray(); }
public SwitchStatement(Token switchToken, Expression condition, List <Token> firstTokens, List <List <Expression> > cases, List <List <Executable> > code, Expression explicitMax, Token explicitMaxToken, TopLevelConstruct owner) : base(switchToken, owner) { if (cases.Count == 0) { throw new ParserException(switchToken, "Switch statement needs cases."); } if (code.Count == 0) { throw new ParserException(switchToken, "Switch statement needs code."); } if (cases[0] == null) { throw new ParserException(switchToken, "Switch statement must start with a case."); } if (cases[cases.Count - 1] != null) { throw new ParserException(switchToken, "Last case in switch statement is empty."); } this.Condition = condition; this.explicitMax = explicitMax; this.explicitMaxToken = explicitMaxToken; List <Chunk> chunks = new List <Chunk>(); int counter = 0; for (int i = 0; i < cases.Count; i += 2) { if (cases[i] == null) { throw new Exception("This should not happen."); } if (code[i + 1] == null) { throw new Exception("This should not happen."); } Chunk chunk = new Chunk(counter++, firstTokens[i], cases[i], code[i + 1]); if (chunk.Code.Length > 0 && chunk.ContainsFallthrough) { throw new ParserException(firstTokens[i], "This switch statement case contains code, but falls through to the next case. Cases that contain code must end with a return or break statement. Alternatively, you may just have mismatched curly braces somewhere."); } chunks.Add(chunk); } this.chunks = chunks.ToArray(); if (this.chunks.Length == 1 && this.chunks[0].Cases.Length == 1 && this.chunks[0].Cases[0] == null) { throw new ParserException(switchToken, "Switches need at least 1 case to indicate type."); } }
public CompileTimeDictionary(Token firstToken, string type, TopLevelConstruct owner) : base(firstToken, owner) { this.Type = type; }
public BaseMethodReference(Token firstToken, Token dotToken, Token stepToken, TopLevelConstruct owner) : base(firstToken, owner) { this.DotToken = dotToken; this.StepToken = stepToken; ClassDefinition cd = null; if (owner is FunctionDefinition) { cd = (ClassDefinition)((FunctionDefinition)owner).Owner; } else if (owner is ClassDefinition) { cd = (ClassDefinition)owner; } else { throw new System.InvalidOperationException(); // this should not happen. } this.ClassToWhichThisMethodRefers = cd.BaseClass; this.FunctionDefinition = this.ClassToWhichThisMethodRefers.GetMethod(this.StepToken.Value, true); if (this.FunctionDefinition == null) { throw new ParserException(this.StepToken, "There is no method named '" + this.StepToken.Value + "' on any base class."); } }
public BaseKeyword(Token token, TopLevelConstruct owner) : base(token, owner) { }
public Ternary(Expression condition, Expression trueValue, Expression falseValue, TopLevelConstruct owner) : base(condition.FirstToken, owner) { this.Condition = condition; this.TrueValue = trueValue; this.FalseValue = falseValue; }
public LibraryFunctionReference(Token token, string name, TopLevelConstruct owner) : base(token, owner) { this.Name = name; }
public Expression CloneValue(Token token, TopLevelConstruct owner) { return(new FloatConstant(token, this.Value, owner)); }
public TopLevelConstruct(Token firstToken, TopLevelConstruct owner, FileScope fileScope) : base(firstToken, owner) { this.FileScope = fileScope; }
public ReturnStatement(Token returnToken, Expression nullableExpression, TopLevelConstruct owner) : base(returnToken, owner) { this.Expression = nullableExpression; }
public SpecialEntity(Token firstToken, TopLevelConstruct owner) : base(firstToken, owner) { }
public EnumValuesFunction(Token firstToken, EnumDefinition enumDef, TopLevelConstruct owner) : base(firstToken, owner) { this.enumDef = enumDef; }