Ejemplo n.º 1
0
func runFile(name string) *parser.Block {
	os.Chdir(filepath.Dir(name))

	file, err := util.NewFile(filepath.Base(name) + "." + util.FileExtension)
	if err != nil {
		reportError(err.Error(), false)
	}

	lex := lexer.NewLexerFromFile(file)

	err = lex.Lex()
	if err != nil {
		reportError(err.Error(), false)
	}

	nodes, err := parser.Nodes(lex.Tokens)
	if err != nil {
		reportError(err.Error(), false)
	}

	block := parser.NewBlock(nodes, nil, file)
	setDefaults(block.Scope)

	err = block.Exec()
	if err != nil {
		reportError(err.Error(), false)
	}

	return block
}
Ejemplo n.º 2
0
func while_(context *parser.FunctionCallContext) error {
	values, err := parser.ValidateArguments(context, "while", parser.VALUE_FUNCTION, parser.VALUE_FUNCTION)

	if err != nil {
		return err
	}

	check := values[0].F

recheck:
	fakeBlock := parser.NewBlock(nil, nil, nil)

	checkErr := check.Exec(fakeBlock, context.Token)

	if checkErr != nil {
		return checkErr
	}

	if fakeBlock.Stack.Len() != 1 || fakeBlock.Stack.Peek(0).(*parser.Value).Type != parser.VALUE_BOOL {
		return util.NewInvalidArgumentError("while", "the callback function provided to while must return 1 boolean value", context.Token.Line, context.Token.Column, context.Token.File)
	}

	if fakeBlock.Stack.Peek(0).(*parser.Value).B {
		runErr := values[1].F.Exec(context.Block, context.Token)

		if runErr != nil {
			return runErr
		}

		goto recheck
	}

	return nil
}
Ejemplo n.º 3
0
func orN(context *parser.FunctionCallContext) error {
	values, err := parser.ValidateArguments(context, "or-n", parser.VALUE_FUNCTION)

	if err != nil {
		return err
	}

	fakeBlock := parser.NewBlock(nil, nil, nil)

	runErr := values[0].F.Exec(fakeBlock, context.Token)

	if runErr != nil {
		return runErr
	}

	result := false

	if fakeBlock.Stack.Len() >= 1 {
		for fakeBlock.Stack.Len() > 0 {
			value := fakeBlock.Stack.Pop().(*parser.Value)

			if value.Type != parser.VALUE_BOOL {
				return util.NewInvalidArgumentError("or-n", "expected a boolean in the function stack", context.Token.Line, context.Token.Column, context.Token.File)
			}

			result = result || value.B
		}
	} else {
		return util.NewInvalidArgumentError("or-n", "expected at least 2 values to compare in function stack", context.Token.Line, context.Token.Column, context.Token.File)
	}

	context.Block.Stack.Push(parser.NewValueFromBool(result))

	return nil
}
Ejemplo n.º 4
0
func useFile(context *parser.FunctionCallContext) error {
	values, err := parser.ValidateArguments(context, "use-file", parser.VALUE_STRING)

	if err != nil {
		return err
	}

	file, err := util.NewFile(values[0].S)
	if err != nil {
		return err
	}

	lex := lexer.NewLexerFromFile(file)

	err = lex.Lex()
	if err != nil {
		return err
	}

	nodes, err := parser.Nodes(lex.Tokens)
	if err != nil {
		return err
	}

	fileBlock := parser.NewBlock(nodes, context.Block, file)
	err = fileBlock.Exec()
	if err != nil {
		return err
	}

	for key, value := range fileBlock.Scope.Symbols {
		if value.Exported {
			context.Block.Scope.SetSymbol(key, value)
		}
	}

	fileBlock.Stack.PopAllToOtherStack(context.Block.Stack)

	return nil
}
Ejemplo n.º 5
0
func runRepl() *parser.Block {
	var tokens []*lexer.Token
	depth := 0

	block := parser.NewBlock(nil, nil, nil)
	setDefaults(block.Scope)

	for {
		reader := bufio.NewReader(os.Stdin)
		fmt.Print("> ")
		data, _ := reader.ReadString('\n')

		lex := lexer.NewLexer([]rune(data))

		err := lex.Lex()
		if err != nil {
			reportError(err.Error(), true)
		} else {
			for _, token := range lex.Tokens {
				tokens = append(tokens, token)
			}

			for _, token := range lex.Tokens {
				if token.IsOpening() {
					depth++
				} else if token.IsClosing() {
					depth--
				}
			}

			if depth <= 0 {
				nodes, err := parser.Nodes(tokens)

				tokens = nil
				depth = 0

				if err != nil {
					reportError(err.Error(), true)
				} else {
					block.Nodes = nodes

					err := block.Exec()
					if err != nil {
						reportError(err.Error(), true)
					}

					if block.Stack.Len() > 0 {
						fmt.Print(util.COLOR_YELLOW)

						for i := 0; i < block.Stack.Len(); i++ {
							fmt.Print(block.Stack.Peek(i).(*parser.Value).String() + " ")
						}

						fmt.Print(util.COLOR_RESET + "\n")
					}
				}
			}
		}
	}

	return block
}
Ejemplo n.º 6
0
func switchFunction(context *parser.FunctionCallContext, fall bool, otherwise bool) error {
	functionName := "switch"

	if fall {
		functionName += "-fallthrough"
	}

	var otherwiseFunction *parser.Function

	if otherwise {
		valuesOtherwise, errOtherwise := parser.ValidateArguments(context, functionName, parser.VALUE_FUNCTION)

		if errOtherwise != nil {
			return errOtherwise
		}

		otherwiseFunction = valuesOtherwise[0].F
	}

	values, err := parser.ValidateArguments(context, functionName, parser.VALUE_FUNCTION)

	if err != nil {
		return err
	}

	conditionFunction := values[0].F

	fakeBlock := parser.NewBlock(nil, nil, nil)

	conditionsErr := conditionFunction.Exec(fakeBlock, context.Token)

	if conditionsErr != nil {
		return conditionsErr
	}

	if fakeBlock.Stack.Len()%2 != 0 {
		return util.NewInvalidArgumentError(functionName, "cannot switch because the stack of the function is unbalanced, missing condition or callback", context.Token.Line, context.Token.Column, context.Token.File)
	}

	any := false
	conditions := 0

	for i := fakeBlock.Stack.Len() - 1; i >= 0; i-- {
		conditions++

		condition := fakeBlock.Stack.Peek(i).(*parser.Value)

		if condition.Type != parser.VALUE_BOOL {
			return util.NewInvalidArgumentError(functionName, "expected a boolean condition for condition "+strconv.Itoa(conditions), context.Token.Line, context.Token.Column, context.Token.File)
		}

		i--

		if condition.B {
			any = true

			callback := fakeBlock.Stack.Peek(i).(*parser.Value)

			if callback.Type != parser.VALUE_FUNCTION {
				return util.NewInvalidArgumentError(functionName, "expected a function callback for condition "+strconv.Itoa(conditions), context.Token.Line, context.Token.Column, context.Token.File)
			}

			runErr := callback.F.Exec(context.Block, context.Token)

			if runErr != nil {
				return runErr
			}

			if !fall {
				break
			}
		}
	}

	if otherwise && !any {
		otherwiseErr := otherwiseFunction.Exec(context.Block, context.Token)

		if otherwiseErr != nil {
			return otherwiseErr
		}
	}

	return nil
}