func main() { log.Trace("-m-", "Opening input file") // Parse debug flags flag.BoolVar(&log.LOG_TOKENS, "log-tokens", false, "Enable list of parsed tokens") flag.BoolVar(&log.LOG_TRACE, "log-trace", false, "Enable trace logging of debug output") flag.BoolVar(&log.EXTENSIONS, "extensions", false, "Enables parser extensions for additional features. See README for a list of these.") flag.Parse() // Init builtin functions ast.InitBuiltins() // Parse command line arguments var file *os.File var err error if flag.NArg() == 0 { log.Trace("-m-", "Reading from stdin") file = os.Stdin } else if flag.NArg() == 1 { log.Trace("-m-", "Reading from file "+flag.Arg(0)) file, err = os.Open(flag.Arg(0)) } else { panic("Must provide filename to read from or no filename at all") } if err != nil { panic("File name provided does not exist") } log.Trace("-m-", "Beginning lex") yyParse(NewLexer(file)) }
// Declares a new variable in the current scope func Declare(name string) { if Scope == nil { log.Trace("sym", "Declaring global variable "+name) GlobalScope[name] = Value{Type: VALUE_UNDEFINED, Written: false} } else { log.Trace("sym", "Declaring scope-local variable "+name) Scope[name] = Value{Type: VALUE_UNDEFINED, Written: false} } }
func (fd FunctionDef) Execute() interface{} { log.Trace("ast", "Defining function "+fd.Name) // Store this function in the symbol table value := Value{Type: VALUE_FUNCTION, Value: fd, Line: fd.Line, Written: true} Declare(fd.Name) AssignToVariable(fd.Name, value, fd.Line) return nil }
func (f FunctionCall) Execute() interface{} { log.Trace("ast", "Executing function "+f.Name) // Create the local stack and return val f.LocalScope = make(map[string]Value) f.ReturnVal = Value{Type: VALUE_UNDEFINED, Line: f.Line} // Retrieve the function definition funVal := GetVariable(f.Name, f.Line) if funVal.Type != VALUE_FUNCTION { log.TypeViolation(f.Line) return f.ReturnVal } funDef := funVal.Value.(FunctionDef) // Check number of arguments if !funDef.ArbitraryArgs && len(f.Args) != len(funDef.ArgNames) { log.TypeViolation(f.Line) return f.ReturnVal } if funDef.ExecMiniscript { // Load the arguments into the local stack for i, name := range funDef.ArgNames { f.LocalScope[name] = f.Args[i].Execute().(Value) } // Save the old scope and set this local as its own scope oldScope := Scope Scope = f.LocalScope // Execute the function retVal := funDef.MSBody.Execute() var nRetVal Value switch retVal.(type) { case Return: nRetVal = retVal.(Return).Value.Execute().(Value) case Value: nRetVal = retVal.(Value) } // Restore the old scope Scope = oldScope return nRetVal } else { funDef.GoBody(f) return nil } }
func (l Loop) Execute() interface{} { log.Trace("ast", "Executing loop") condition := Value{Type: VALUE_BOOLEAN, Value: true} for { if l.PreCheck { condition = l.Conditional.Execute().(Value).ToBoolean() if condition.Type != VALUE_BOOLEAN { log.ConditionError(l.Line) return nil } } var breakMet = false if condition.Value.(bool) { LoopDepth++ jump := l.Body.Execute() LoopDepth-- switch jump.(type) { case Break: breakMet = true } } else { break } if breakMet { break } if !l.PreCheck { condition = l.Conditional.Execute().(Value).ToBoolean() if condition.Type != VALUE_BOOLEAN { log.ConditionError(l.Line) return nil } } } return nil }