hussar-lang/hussar

View on GitHub
object/object.go

Summary

Maintainability
A
1 hr
Test Coverage
package object

import (
    "bytes"
    "fmt"
    "strings"

    "github.com/hussar-lang/hussar/ast"
    "github.com/ttacon/chalk"
)

type ObjectType string

const (
    ERROR_OBJ        = "ERROR"
    INTEGER_OBJ      = "INTEGER"
    STRING_OBJ       = "STRING"
    BOOLEAN_OBJ      = "BOOLEAN"
    NULL_OBJ         = "NULL"
    RETURN_VALUE_OBJ = "RETURN_VALUE"
    FUNCTION_OBJ     = "FUNCTION"
    BUILTIN_OBJ      = "BUILTIN"
    ARRAY_OBJ        = "ARRAY"
    EXIT_OBJ         = "EXIT"
)

type Object interface {
    Type() ObjectType
    Inspect() string
}

// === Errors ===
type Error struct {
    Severity string
    Message  string
}

func (e *Error) Type() ObjectType { return ERROR_OBJ }
func (e *Error) Inspect() string {
    errColor := chalk.Red.NewStyle().WithTextStyle(chalk.Bold).Style
    warnColor := chalk.Yellow.NewStyle().WithTextStyle(chalk.Bold).Style

    switch e.Severity {
    case "warn":
        return warnColor("[WARN]  ") + e.Message
    default:
        return errColor("[ERROR] ") + e.Message
    }
}

// === Integer ===
type Integer struct {
    Value int64
}

func (i *Integer) Type() ObjectType { return INTEGER_OBJ }
func (i *Integer) Inspect() string  { return fmt.Sprintf("%d", i.Value) }

// === String ===
type String struct {
    Value string
}

func (s *String) Type() ObjectType { return STRING_OBJ }
func (s *String) Inspect() string  { return s.Value }

// === Boolean ===
type Boolean struct {
    Value bool
}

func (b *Boolean) Type() ObjectType { return BOOLEAN_OBJ }
func (b *Boolean) Inspect() string  { return fmt.Sprintf("%t", b.Value) }

// === Null ===
type Null struct{}

func (n *Null) Type() ObjectType { return NULL_OBJ }
func (n *Null) Inspect() string  { return "null" }

// === Return ===
type ReturnValue struct {
    Value Object
}

func (rv *ReturnValue) Type() ObjectType { return RETURN_VALUE_OBJ }
func (rv *ReturnValue) Inspect() string  { return rv.Value.Inspect() }

// === Function ===
type Function struct {
    //Name string        TODO: to be used to not have to bind to a variable explicitly
    Parameters []*ast.Identifier
    Body       *ast.BlockStatement
    Env        *Environment
}

func (f *Function) Type() ObjectType { return FUNCTION_OBJ }
func (f *Function) Inspect() string {
    var out bytes.Buffer

    params := []string{}
    for _, p := range f.Parameters {
        params = append(params, p.String())
    }

    out.WriteString("fn")
    out.WriteString("(")
    out.WriteString(strings.Join(params, ", "))
    out.WriteString(") {\n")
    out.WriteString(f.Body.String())
    out.WriteString("\n}")

    return out.String()
}

// === Builtin ===
type BuiltinFunction func(args ...Object) Object

type Builtin struct {
    Fn BuiltinFunction
}

func (b *Builtin) Type() ObjectType { return BUILTIN_OBJ }
func (b *Builtin) Inspect() string  { return "builtin function" }

// === Array ===
type Array struct {
    Elements []Object
}

func (a *Array) Type() ObjectType { return ARRAY_OBJ }
func (a *Array) Inspect() string {
    var out bytes.Buffer

    elements := []string{}
    for _, e := range a.Elements {
        elements = append(elements, e.Inspect())
    }

    out.WriteString("[")
    out.WriteString(strings.Join(elements, ", "))
    out.WriteString("]")

    return out.String()
}

// === Exit ===
type Exit struct {
    ExitCode *ast.Expression
}

func (e *Exit) Type() ObjectType { return EXIT_OBJ }
func (e *Exit) Inspect() string {
    var out bytes.Buffer

    out.WriteString("exit()")

    return out.String()
}