func verifyInnerStatements(innerStatements []Statement, line int) parser.SyntaxError { numOfStatements := len(innerStatements) if numOfStatements == 0 { return parser.NewSyntaxError("No inner statement found", line, 0) } else if _, ok := innerStatements[numOfStatements-1].(*ReturnStatement); !ok { return parser.NewSyntaxError("Last statement in function is not a returnable statement", line, 0) } else { for _, s := range innerStatements[:numOfStatements-1] { if _, ok := s.(*LetStatement); !ok { return parser.NewSyntaxError("Only the last statement in function can be a returnable statement", line, 0) } } } return nil }
func ToRpn(line string, lineNum int, fm FunctionMap) ([]RpnValue, parser.SyntaxError) { rpn, err := toRpn(line, []RpnValue{}, []RpnValue{}, fm) if err != nil { return nil, parser.NewSyntaxError(err.Error(), lineNum, 0) } return rpn, nil }
func (fs LambdaStatement) Parse(block string, lineNum int, nextBlockScanner *parser.ScanPeeker, factory *StatementFactory) (Statement, parser.SyntaxError) { lines := parser.Lines(block) factory = fetchNewFactory(factory) typeDef, err, rest := expressionParsing.ParseTypeDef(lines[0]) if err != nil { return nil, parser.NewSyntaxError(err.Error(), lineNum, 0) } var ftd expressionParsing.FuncTypeDefinition var ok bool if ftd, ok = typeDef.(expressionParsing.FuncTypeDefinition); !ok { return nil, nil } var codeBlock []string if len(strings.TrimSpace(rest)) > 0 { var first string if len(lines) > 1 { return nil, parser.NewSyntaxError("Inline lambdas can only be one line", lineNum, 0) } else if first, rest = parser.Tokenize(rest); first != "->" { return nil, parser.NewSyntaxError("Misplaced tokens: "+rest, lineNum, 0) } codeBlock = []string{rest} } else { codeBlock = parser.RemoveTabs(lines[1:]) } innerStatements, synErr := fetchInnerStatements(codeBlock, factory, lineNum+1) if synErr != nil { return nil, synErr } synErr = verifyInnerStatements(innerStatements, lineNum) if synErr != nil { return nil, synErr } return newLambdaStatement(lineNum, ftd, innerStatements, fs.packageLevel, fs.name), nil }
func ToGoExpression(line string, lineNum int, fm FunctionMap) (string, TypeDefinition, parser.SyntaxError) { rpn, synErr := ToRpn(line, lineNum, fm) if synErr != nil { return "", nil, synErr } result, td, err := ToInfix(rpn, fm) if err != nil { return "", nil, parser.NewSyntaxError(err.Error(), lineNum, 0) } return result, td, nil }
func (sf *StatementFactory) Read(blockPeeker *parser.ScanPeeker) (Statement, parser.SyntaxError) { ok, value, lineNum := blockPeeker.Read() if !ok { if blockPeeker.Err() != nil { return nil, parser.NewSyntaxError(blockPeeker.Err().Error(), lineNum, 0) } return nil, nil } for _, s := range sf.statements { statement, err := s.Parse(value, lineNum, blockPeeker, sf) if err != nil { return nil, err } else if statement != nil { return statement, nil } } return nil, nil }
func writeGeneratedBlocks(factory *statementTypes.StatementFactory, peeker *parser.ScanPeeker, fm expressionParsing.FunctionMap, writer io.Writer) parser.SyntaxError { s, synErr := factory.Read(peeker) if synErr != nil { return synErr } if s != nil { code, _, synErr := s.GenerateGo(fm) if synErr != nil { return synErr } _, err := io.WriteString(writer, code+"\n\n") if err != nil { return parser.NewSyntaxError(err.Error(), 0, 0) } return writeGeneratedBlocks(factory, peeker, fm, writer) } return nil }
func (ds LetStatement) Parse(block string, lineNum int, nextBlockScanner *parser.ScanPeeker, factory *StatementFactory) (Statement, parser.SyntaxError) { lines := parser.Lines(block) ok, varName, restOfLine := splitEquals(lines[0]) if ok { if ds.packageLevel { factory = adjustFactory(varName, factory) } combinedLine := parser.FromLines(append([]string{restOfLine}, lines[1:]...)) peeker := parser.NewScanPeekerStr(combinedLine, lineNum) st, err := factory.Read(peeker) if err != nil { return nil, err } return newLetStatement(varName, combinedLine, lineNum, st), nil } if ds.packageLevel { return nil, parser.NewSyntaxError(fmt.Sprintf("Unknown statement: %s", lines[0]), lineNum, 0) } else { return nil, nil } }
func (ds *LetStatement) GenerateGo(fm expressionParsing.FunctionMap) (string, expressionParsing.TypeDefinition, parser.SyntaxError) { innerCode, returnType, synErr := ds.innerStatement.GenerateGo(fm.NextScopeLayer()) if synErr != nil { return "", nil, synErr } name, err := fm.AddFunction(ds.varName, returnType) if err != nil { return "", nil, parser.NewSyntaxError(err.Error(), 0, 0) } var genCode string if _, ok := returnType.(expressionParsing.FuncTypeDefinition); ok { if ls, ok := ds.innerStatement.(*LambdaStatement); ok && ls.packageLevel { genCode = innerCode } else { genCode = fmt.Sprintf("var %s %s\n%s = %s", name, returnType.GenerateGo(), name, innerCode) } } else { genCode = fmt.Sprintf("var %s func() %s\n%s = func(){\n\treturn %s\n}", name, returnType.GenerateGo(), name, innerCode) } return genCode, returnType, nil }