protected override void VisitTypeSyntax(TypeSyntax pNode) { //TODO i need to have <T> after methods so we can define our generic types and propagate them foreach (var a in pNode.GenericArguments) { Visit(a); } var result = _unit.FromString(pNode, out SmallType type); switch (result) { //case Compiler.FindResult.NotFound: // CompilerErrors.UndeclaredType(name, pNode.Span); // break; case Compiler.FindResult.IncorrectScope: CompilerErrors.TypeNotInScope(SyntaxHelper.GetFullTypeName(pNode), pNode.Span); break; } if (type.IsGenericType) { type = _unit.MakeConcreteType(type, SyntaxHelper.SelectNodeTypes(pNode.GenericArguments)); } pNode.SetType(type); if (pNode.Namespace != null && !_unit.HasReference(pNode.Namespace.Value)) { CompilerErrors.NamespaceNotDefined(pNode.Namespace, pNode.Span); } }
protected override void VisitAssignmentSyntax(AssignmentSyntax pNode) { base.VisitAssignmentSyntax(pNode); if (pNode.Value.Type == SmallTypeCache.NoValue) { CompilerErrors.ExpressionNoValue(pNode.Value.Span); } var isTuple = pNode.Value.Type.IsTuple; for (int i = 0; i < pNode.Variables.Count; i++) { //Check if we are assigning to a const variable if (_locals.TryGetVariable(pNode.Variables[i].Value, out LocalDefinition ld) && ld.IsConst) { CompilerErrors.CannotAssignCost(pNode.Variables[i], pNode.Variables[i].Span); } var t = isTuple ? pNode.Value.Type.GetFieldType(i) : pNode.Value.Type; //We have to set the type of discards so the tuple is created properly if (SyntaxHelper.IsDiscard(pNode.Variables[i])) { ((DiscardSyntax)pNode.Variables[i]).SetType(t); } } }
protected override SyntaxNode VisitBlockSyntax(BlockSyntax pNode) { //Rewrite any statements after the return statement to be a NOP List <SyntaxNode> statements = new List <SyntaxNode>(pNode.Statements.Count); bool returnFound = false; for (int i = 0; i < pNode.Statements.Count; i++) { if (!returnFound) { statements.Add(Visit(pNode.Statements[i])); } else { CompilerErrors.UnreachableCode(pNode.Statements[i].Span); } if (pNode.Statements[i].SyntaxType == SyntaxType.Return) { returnFound = true; } } return(SyntaxFactory.Block(statements)); }
protected override void VisitIdentifierSyntax(IdentifierSyntax pNode) { _locals.SetValue(pNode.Value, new LocalReference(pNode.Span, pNode.Value, true)); var currentStruct = Struct; var currentType = CurrentType; if (currentType != null) { var definition = currentType.GetField(pNode.Value); //Only the defining struct can access hidden fields if (definition.Visibility == FieldVisibility.Hidden && currentStruct != currentType) { //Check if the struct is a trait that implements the current type //This will allow implementing traits to access the struct's private fields if (currentStruct == null || !currentStruct.IsTrait || !currentType.IsAssignableFrom(currentStruct)) { CompilerErrors.AccessPrivateMember(pNode, pNode.Span); } } } if (currentStruct != null && Store.GetValueOrDefault <bool>("InConstructor") && Store.GetValueOrDefault <bool>("InAssignment")) { _usedFields.Add(pNode.Value); } base.VisitIdentifierSyntax(pNode); }
private void TryPolyStruct(TypeDefinitionSyntax pNode, StructInitializerSyntax pInitializer) { //Number of generic type parameters on the type does not match //the number of type arguments specified at the initialization site if (pInitializer.Struct.GenericArguments.Count != pNode.TypeParameters.Count) { CompilerErrors.TypePolyArgumentCount(pInitializer.Struct, pNode.TypeParameters.Count, pInitializer.Span); } //We just create a dictionary of T,int; T2,string; etc... and feed that to the type //When the type is emitted it will create a copy of itself for each unique generic argument Dictionary <string, SmallType> types = new Dictionary <string, SmallType>(); for (int i = 0; i < pNode.TypeParameters.Count; i++) { types.Add(pNode.TypeParameters[i], pInitializer.Struct.GenericArguments[i].Type); } pNode.AddTypeMapping(types); //We also need to add the same type mappings for any trait implementations var name = SyntaxHelper.GetFullTypeName(pNode.GetApplicableType()); if (_implements.ContainsKey(name)) { foreach (var impl in _implements[name]) { impl.AddTypeMapping(types); } } }
protected override void VisitStructInitializerSyntax(StructInitializerSyntax pNode) { //Check if the type exists if (pNode.Struct.Type == SmallTypeCache.Undefined) { CompilerErrors.UndeclaredType(pNode.Struct.ToString(), pNode.Span); } //Check if the type is a trait else if (pNode.Struct.Type.IsTrait) { CompilerErrors.AttemptDeclareTrait(pNode.Struct.Type, pNode.Span); } //Ensure the constructor arguments else if (pNode.Struct.Type.HasDefinedConstructor()) { var m = pNode.Struct.Type.GetConstructor(); for (int i = 0; i < m.ArgumentTypes.Count; i++) { if (!CanCast(pNode.Arguments[i].Type, m.ArgumentTypes[i])) { CompilerErrors.TypeCastError(pNode.Arguments[i].Type, m.ArgumentTypes[i], pNode.Arguments[i].Span); } } } base.VisitStructInitializerSyntax(pNode); }
protected override void VisitUnaryExpressionSyntax(UnaryExpressionSyntax pNode) { switch (pNode.Operator) { case UnaryExpressionOperator.Not: if (!CanCast(pNode.Value.Type, SmallTypeCache.Boolean)) { CompilerErrors.TypeCastError(pNode.Value.Type, SmallTypeCache.Boolean, pNode.Value.Span); } break; case UnaryExpressionOperator.Length: if (!pNode.Value.Type.IsArray) { CompilerErrors.TypeCastError(pNode.Value.Type.ToString(), "array", pNode.Span); } break; case UnaryExpressionOperator.PreDecrement: case UnaryExpressionOperator.PreIncrement: case UnaryExpressionOperator.PostDecrement: case UnaryExpressionOperator.PostIncrement: case UnaryExpressionOperator.Negative: if (!TypeHelper.IsInt(pNode.Value.Type)) { CompilerErrors.TypeCastError(pNode.Value.Type, SmallTypeCache.Int, pNode.Span); } break; } base.VisitUnaryExpressionSyntax(pNode); }
private Token NextSymbol() { //We have to watch for whitespace before and after comments //Otherwise we could begin parsing a token starting with whitespace SkipWhitespace(); SkipComments(); SkipWhitespace(); if (_tokenizer.EOF) { return(new Token(TokenType.EndOfFile, 3)); } _length = 0; _tokenizer.StartToken(); //Identifiers if (char.IsLetter(_tokenizer.Current) || _tokenizer.Current == '_') { return(CreateIdentifier()); } //Numbers if (char.IsDigit(_tokenizer.Current)) { return(CreateNumber()); } //Strings if (_tokenizer.Current == '"') { return(CreateString()); } //Annotation if (_tokenizer.Current == '@') { return(CreateAnnotation()); } //Symbols and keywords TrieNode t = _keywords.Root; TrieNode result = t; while ((t = t.FindChild(_tokenizer.Current)) != null) { result = t; Eat(); } if (!result.Leaf) { var span = new TextSpan(_tokenizer.Index, _tokenizer.Index + 1, _tokenizer.Line, _tokenizer.Column, Source, SourcePath); CompilerErrors.UnknownCharacter(_tokenizer.Current, span); Eat(); return(CreateToken(TokenType.Unknown)); } return(CreateToken(result.Type)); }
protected override void VisitTypedIdentifierSyntax(TypedIdentifierSyntax pNode) { if (pNode.Type == SmallTypeCache.Undefined) { CompilerErrors.UndeclaredType(pNode.TypeNode.Value, pNode.Span); } base.VisitTypedIdentifierSyntax(pNode); }
protected override void VisitWhileSyntax(WhileSyntax pNode) { if (!CanCast(pNode.Condition.Type, SmallTypeCache.Boolean)) { CompilerErrors.TypeCastError(pNode.Condition.Type, SmallTypeCache.Boolean, pNode.Condition.Span); } base.VisitWhileSyntax(pNode); }
protected override void VisitDeclarationSyntax(DeclarationSyntax pNode) { if (pNode.IsConst && !IsConstant(null, pNode.Value)) { CompilerErrors.ConstantNotConstantValue(pNode.Value.Span); } base.VisitDeclarationSyntax(pNode); }
protected override void VisitTypeDefinitionSyntax(TypeDefinitionSyntax pNode) { if (pNode.DefinitionType != DefinitionTypes.Implement && pNode.DeclaredType.Namespace != null) { CompilerErrors.StructNamespace(pNode.Span); } base.VisitTypeDefinitionSyntax(pNode); }
protected override void VisitArrayLiteralSyntax(ArrayLiteralSyntax pNode) { if (pNode.Type == SmallTypeCache.Undefined) { CompilerErrors.UndeclaredType(pNode.TypeNode.Value, pNode.Span); } base.VisitArrayLiteralSyntax(pNode); }
public virtual void WriteCompileError(string traceMsg) { string objectName = GetType().Name; traceMsg = string.Format(traceMsg, objectName, string.IsNullOrEmpty(Name) ? objectName : Name); CompilerErrors.Add(traceMsg); WriteOutput(traceMsg); }
private bool AddMethodToCache(SmallType pType, MethodSyntax pMethod, out MethodDefinition pDefinition) { //Check for duplicate method definitions Compiler.FindResult found; if (pMethod.SyntaxType == SyntaxType.Method) { found = _unit.MethodExists(pType, pMethod); } else if (pMethod.SyntaxType == SyntaxType.CastDefinition) { found = _unit.CastExists(pType, pMethod.Type, out MethodDefinition pDef); } else { throw new InvalidOperationException("Unknown method type " + pMethod.SyntaxType.ToString()); } if (found != Compiler.FindResult.NotFound) { if (pMethod.SyntaxType == SyntaxType.Method) { CompilerErrors.MethodDuplicate(pMethod, pMethod.Span); } else if (pMethod.SyntaxType == SyntaxType.CastDefinition) { CompilerErrors.CastDuplicate(pMethod.Parameters[0].Type, pMethod.Type, pMethod.Span); } pDefinition = default; return(false); } else { //Create the tuple type if we are returning more than one value from a method //This will cache it in our SmallTypeCache so it can be found later if (pMethod.ReturnValues.Count > 1) { SmallTypeCache.GetOrCreateTuple(SyntaxHelper.SelectNodeTypes(pMethod.ReturnValues)); } //Set method and return types foreach (var p in pMethod.Parameters) { _unit.FromString(p.TypeNode, out SmallType t); p.TypeNode.SetType(t); } foreach (var r in pMethod.ReturnValues) { _unit.FromString(r, out SmallType t); r.SetType(t); } //Add method pDefinition = _unit.AddMethod(pType, pMethod); return(true); } }
protected override void VisitReturnSyntax(ReturnSyntax pNode) { for (int i = 0; i < Math.Min(_methodReturns.Length, pNode.Values.Count); i++) { if (!CanCast(pNode.Values[i].Type, _methodReturns[i])) { CompilerErrors.TypeCastError(pNode.Values[i].Type, _methodReturns[i], pNode.Values[i].Span); } } base.VisitReturnSyntax(pNode); }
public override bool Compile() { base.Compile(); Actions.ForEach(c => { c.Compile(); c.CompilerErrors.ToList().ForEach(d => CompilerErrors.Add(d)); }); return(IsCompiled); }
protected override void VisitMethodSyntax(MethodSyntax pNode) { for (int i = 0; i < pNode.ReturnValues.Count; i++) { if (pNode.ReturnValues[i].Type == SmallTypeCache.Undefined) { CompilerErrors.UndeclaredType(pNode.ReturnValues[i].Value, pNode.ReturnValues[i].Span); } } _methodReturns = SyntaxHelper.SelectNodeTypes(pNode.ReturnValues); base.VisitMethodSyntax(pNode); }
protected override void VisitTernaryExpression(TernaryExpressionSyntax pNode) { if (!CanCast(pNode.Condition.Type, SmallTypeCache.Boolean)) { CompilerErrors.TypeCastError(pNode.Condition.Type, SmallTypeCache.Boolean, pNode.Condition.Span); } if (pNode.Left.Type != pNode.Right.Type) { CompilerErrors.TypeCastError(pNode.Left.Type, pNode.Right.Type, pNode.Span); } base.VisitTernaryExpression(pNode); }
protected override void VisitBinaryExpressionSyntax(BinaryExpressionSyntax pNode) { switch (pNode.Operator) { case BinaryExpressionOperator.And: case BinaryExpressionOperator.Or: if (!CanCast(pNode.Left.Type, SmallTypeCache.Boolean)) { CompilerErrors.TypeCastError(pNode.Left.Type, SmallTypeCache.Boolean, pNode.Span); } if (!CanCast(pNode.Right.Type, SmallTypeCache.Boolean)) { CompilerErrors.TypeCastError(pNode.Right.Type, SmallTypeCache.Boolean, pNode.Span); } break; case BinaryExpressionOperator.BitwiseAnd: case BinaryExpressionOperator.BitwiseOr: if (!CanCast(pNode.Left.Type, SmallTypeCache.Int)) { CompilerErrors.TypeCastError(pNode.Left.Type, SmallTypeCache.Int, pNode.Span); } if (!CanCast(pNode.Right.Type, SmallTypeCache.Int)) { CompilerErrors.TypeCastError(pNode.Right.Type, SmallTypeCache.Int, pNode.Span); } break; case BinaryExpressionOperator.LeftBitShift: case BinaryExpressionOperator.RightBitShift: if (pNode.Left.Type != SmallTypeCache.Undefined && pNode.Right.Type != SmallTypeCache.Undefined && !CanCast(pNode.Left.Type, pNode.Right.Type)) { CompilerErrors.TypeCastError(pNode.Left.Type, pNode.Right.Type, pNode.Span); } break; default: //Types can be undefined if the type was not found. //These errors will be reported when the type is first found if (pNode.Left.Type != SmallTypeCache.Undefined && pNode.Right.Type != SmallTypeCache.Undefined && BinaryExpressionSyntax.GetResultType(pNode.Left.Type, pNode.Operator, pNode.Right.Type) == SmallTypeCache.Undefined) { CompilerErrors.TypeCastError(pNode.Left.Type, pNode.Right.Type, pNode.Span); } break; } base.VisitBinaryExpressionSyntax(pNode); }
protected override void VisitCaseSyntax(CaseSyntax pNode) { var caseType = Store.GetValue <SmallType>("CaseType"); foreach (var c in pNode.Conditions) { if (!CanCast(caseType, c.Type)) { CompilerErrors.TypeCastError(c.Type, caseType, pNode.Span); } } base.VisitCaseSyntax(pNode); }
protected override void VisitTypedIdentifierSyntax(TypedIdentifierSyntax pNode) { base.VisitTypedIdentifierSyntax(pNode); if (_locals.IsVariableDefinedInScope(pNode.Value)) { CompilerErrors.IdentifierAlreadyDeclared(pNode, pNode.Span); } else { _locals.DefineVariableInScope(pNode.Value, LocalDefinition.Create(false, pNode.Type)); } }
public override void SyntaxError( IRecognizer recognizer, IToken offendingSymbol, int line, int charPositionInLine, string msg, RecognitionException e) { CompilerErrors.Add( new CompilerError { Column = charPositionInLine, Line = line, Message = msg, Exception = e }); Console.WriteLine($"[{line}/{charPositionInLine}] - {msg}"); }
protected override void VisitArrayAccessSyntax(ArrayAccessSyntax pNode) { if (!CanCast(pNode.Index.Type, SmallTypeCache.Int)) { CompilerErrors.TypeCastError(pNode.Index.Type, SmallTypeCache.Int, pNode.Index.Span); } if (!pNode.Identifier.Type.IsArray) { CompilerErrors.CannotIndex(pNode.Identifier.Type, pNode.Span); } base.VisitArrayAccessSyntax(pNode); }
protected override void VisitBreakSyntax(BreakSyntax pNode) { if (!Store.GetValueOrDefault <bool>("CanBreak")) { CompilerErrors.InvalidBreakLocation(pNode.Span); } else { if (pNode.CountAsInt >= _breakCount) { CompilerErrors.InvalidBreakCount(_breakCount - 1, pNode.Span); } } }
protected override void VisitIdentifierSyntax(IdentifierSyntax pNode) { if (CurrentType != null || !_unit.IsTypeDefined(Namespace, pNode.Value)) { //Normal identifier, continue as usual if (!IsVariableDefined(pNode.Value, out SmallType type)) { if (CurrentType == null) { //Generate a slightly different error message if we are in a struct //This can happen if we forget self if (Struct != null) { CompilerErrors.IdentifierNotDeclaredSelf(pNode, pNode.Span); } else { CompilerErrors.IdentifierNotDeclared(pNode, pNode.Span); } } else { CompilerErrors.IdentifierNotDeclared(CurrentType, pNode, pNode.Span); } } else { pNode.SetType(type); } } else { //Shared or enum value var result = _unit.FromString(Namespace, pNode.Value, out SmallType t); switch (result) { case Compiler.FindResult.Found: pNode.SetType(t); break; case Compiler.FindResult.IncorrectScope: CompilerErrors.TypeNotInScope(pNode.Value, pNode.Span); break; case Compiler.FindResult.NotFound: CompilerErrors.UndeclaredType(pNode.Value, pNode.Span); break; } } }
protected override void VisitModuleSyntax(ModuleSyntax pNode) { _locals = new ScopeCache <LocalReference>(); _locals.AddScope(); using (var v = Store.AddValue <string>("RunMethod", null)) { base.VisitModuleSyntax(pNode); if (pNode == _mainModule && v.Value == null) { CompilerErrors.NoRunMethod(pNode.Span); } } _locals.RemoveScope(); }
protected override void VisitAssignmentSyntax(AssignmentSyntax pNode) { var isTuple = pNode.Value.Type.IsTuple; for (int i = 0; i < pNode.Variables.Count; i++) { var valueType = isTuple ? pNode.Value.Type.GetFieldType(i) : pNode.Value.Type; if (!CanCast(pNode.Variables[i].Type, valueType)) { CompilerErrors.TypeCastError(pNode.Variables[i].Type, valueType, pNode.Span); } } base.VisitAssignmentSyntax(pNode); }
public override bool Compile() { base.Compile(); foreach (ServiceActionInput sai in ServiceActionInputs) { sai.Compile(); sai.CompilerErrors.ToList().ForEach(c => CompilerErrors.Add(c)); } if (CompilerErrors.Count > 0) { return(IsCompiled); } switch (ActionType) { case enActionType.InvokeDynamicService: if (string.IsNullOrEmpty(ServiceName)) { WriteCompileError(Resources.CompilerError_MissingServiceName); } break; case enActionType.Workflow: break; default: //A Source Name is required except in the case of Management Dynamic Services if (string.IsNullOrEmpty(SourceName) && ActionType != enActionType.InvokeManagementDynamicService) { WriteCompileError(Resources.CompilerError_MissingSourceName); } if (string.IsNullOrEmpty(SourceMethod)) { WriteCompileError(Resources.CompilerError_MissingSourceMethod); } //A source is required except in the case of Management Dynamic Services if (Source == null && ActionType != enActionType.InvokeManagementDynamicService) { WriteCompileError(Resources.CompilerError_SourceNotFound); } break; } return(IsCompiled); }
protected override void VisitDeclarationSyntax(DeclarationSyntax pNode) { Visit(pNode.Value); var isTuple = pNode.Value.Type.IsTuple; for (int i = 0; i < pNode.Variables.Count; i++) { if (!SyntaxHelper.IsDiscard(pNode.Variables[i])) { if (_locals.IsVariableDefinedInScope(pNode.Variables[i].Value)) { CompilerErrors.IdentifierAlreadyDeclared(pNode.Variables[i], pNode.Span); } else { //We do not allow variables to have the same names as types //This makes it easier to check for "static" method/fields if (SmallTypeCache.IsTypeDefined(pNode.Variables[i].Value)) { CompilerErrors.ValueDefinedAsType(pNode.Variables[i], pNode.Variables[i].Span); } else { //For tuple types we set the individual variables to the tuple field type... not the tuple itself var t = isTuple ? pNode.Value.Type.GetFieldType(i) : pNode.Value.Type; //Report expression errors and change the type to Undefined so we don't get further no expression errors if (pNode.Value.Type == SmallTypeCache.NoValue) { CompilerErrors.ExpressionNoValue(pNode.Value.Span); t = SmallTypeCache.Undefined; } pNode.Variables[i].SetType(t); _locals.DefineVariableInScope(pNode.Variables[i].Value, LocalDefinition.Create(pNode.IsConst, pNode.Variables[i].Type)); } } } } //Check that we are declaring the proper number of variables if (isTuple && pNode.Value.Type.GetFieldCount() != pNode.Variables.Count) { CompilerErrors.DeclarationCountMismatch(pNode.Value.Type.GetFieldCount(), pNode.Variables.Count, pNode.Span); } }