private Expression MakePathExpression(params string[] pieces) { Debug.Assert(pieces.Length > 0); Expression result = new Expression.Identifier(null, pieces[0]); foreach (var piece in pieces.Skip(1)) { result = new Expression.DotPath(null, result, piece); } // TODO: compile status? SymbolResolution.Resolve(SymbolTable, result); return(result); }
protected override object?Visit(Expression.DotPath dot) { base.Visit(dot); var leftType = System.TypeOf(dot.Left); if (leftType.Equals(Type.Type_)) { // Static member access, we need the type value itself var leftValue = System.EvaluateType(dot.Left); var token = ((Syntax.ParseTree.Expression.DotPath?)dot.ParseTreeNode)?.Right; var _ = token == null ? leftValue.DefinedScope.Reference(dot.Right, System) : leftValue.DefinedScope.Reference(token, System); } else if (leftType is Type.Struct structType) { // Field access if (!(structType.Fields.ContainsKey(dot.Right))) { var rightIdent = (dot.ParseTreeNode as Syntax.ParseTree.Expression.DotPath)?.Right; var err = rightIdent == null ? new UndefinedSymbolError(dot.Right) : new UndefinedSymbolError(rightIdent); err.Context = "field access"; err.SimilarExistingNames = structType.Fields.Keys .Where(f => StringMetrics.OptimalStringAlignmentDistance(f, dot.Right) <= 2); System.Report(err); } } else { // TODO throw new NotImplementedException(); } return(null); }
private Expression ParsePostfixExpression(ExprState state) { var result = ParseAtomicExpression(state); while (true) { var peek = Peek(); if (PostfixOperators.Contains(peek.Type)) { var op = Next(); result = new Expression.Postfix(result, op); } else if (peek.Type == TokenType.OpenParen) { var openParen = Expect(null, null, TokenType.OpenParen); // Call expression var args = new List <WithComma <Expression> >(); while (Peek().Type != TokenType.CloseParen) { var arg = ParseExpression(ExprState.None); var hasComma = Match(TokenType.Comma, out var comma); args.Add(new WithComma <Expression>(arg, comma)); if (!hasComma) { break; } } var closeParen = Expect("call expression", openParen, TokenType.CloseParen); result = new Expression.Call(result, openParen, args, closeParen); } else if (peek.Type == TokenType.OpenBracket) { var openBracket = Expect(null, null, TokenType.OpenBracket); // Subscript expression var index = ParseExpression(ExprState.None); var closeBracket = Expect("subscript expression", openBracket, TokenType.CloseBracket); result = new Expression.Subscript(result, openBracket, index, closeBracket); } else if (!state.HasFlag(ExprState.TypeOnly) && !state.HasFlag(ExprState.NoBraced) && peek.Type == TokenType.OpenBrace) { // Struct instantiation var openBrace = Expect(null, null, TokenType.OpenBrace); var fields = new List <Expression.StructValue.Field>(); while (Peek().Type != TokenType.CloseBrace) { fields.Add(ParseStructValueField()); } var closeBrace = Expect("struct instantiation", openBrace, TokenType.CloseBrace); result = new Expression.StructValue(result, openBrace, fields, closeBrace); } else if (peek.Type == TokenType.Dot) { // Dot path var dot = Expect(null, null, TokenType.Dot); var ident = Expect("dot path expression", null, TokenType.Identifier); result = new Expression.DotPath(result, dot, ident); } else { break; } } return(result); }