Skip to content

Commit

Permalink
Merge VariableValue into ConcreteValue
Browse files Browse the repository at this point in the history
  • Loading branch information
LucaScorpion committed Apr 11, 2021
1 parent f34e3f0 commit ac6e8e6
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 62 deletions.
8 changes: 4 additions & 4 deletions internal/parser/parseFunctions.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func (p *parser) parseFuncCall() (runtime.Instruction, error) {
}

// Collect all function argument tokens.
var argValues []runtime.Value
var argValues []*runtime.Value
for next := p.peekToken(); next.TokenType != lexer.TokenEOF && next.TokenType != lexer.TokenNewline; next = p.peekToken() {
if next.IsValueToken() {
val, err := p.parseValue()
Expand All @@ -105,7 +105,7 @@ func (p *parser) parseFuncCall() (runtime.Instruction, error) {
// For "any" kind args, change their kind in context to match the function's param kind.
if resolvedKind == runtime.AnyKind {
resolvedKind = funcVal.ParamKind(i)
p.ctx.SetValue(argI.(runtime.VariableValue).Ref(), runtime.NewEmptyValue(resolvedKind))
p.ctx.SetValue(argI.RawValue().(string), runtime.NewEmptyValue(resolvedKind))
}

argKinds[i] = resolvedKind
Expand Down Expand Up @@ -134,7 +134,7 @@ func (p *parser) parseFuncCall() (runtime.Instruction, error) {
return runtime.NewFunctionCall(funcVal, argValues), nil
}

func (p *parser) parseValue() (runtime.Value, error) {
func (p *parser) parseValue() (*runtime.Value, error) {
valueToken := p.readToken()
switch valueToken.TokenType {
case lexer.TokenLiteralString:
Expand Down Expand Up @@ -168,7 +168,7 @@ func (p *parser) parseValue() (runtime.Value, error) {
}
}

func (p *parser) parseFuncDef() (runtime.Value, error) {
func (p *parser) parseFuncDef() (*runtime.Value, error) {
// The opening paren is already read.

// Start a new parser context.
Expand Down
8 changes: 4 additions & 4 deletions internal/runtime/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ package runtime
import "fmt"

type Context struct {
values map[string]ConcreteValue
values map[string]*Value
parent *Context
}

func NewContext(parent *Context) *Context {
return &Context{
values: map[string]ConcreteValue{},
values: map[string]*Value{},
parent: parent,
}
}
Expand All @@ -29,11 +29,11 @@ func (c *Context) Parent() *Context {
return c.parent
}

func (c *Context) SetValue(name string, v ConcreteValue) {
func (c *Context) SetValue(name string, v *Value) {
c.values[name] = v
}

func (c *Context) GetValue(name string) ConcreteValue {
func (c *Context) GetValue(name string) *Value {
if v, ok := c.values[name]; ok {
return v
}
Expand Down
14 changes: 7 additions & 7 deletions internal/runtime/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"reflect"
)

var nativeFunctions = map[string]ConcreteValue{
var nativeFunctions = map[string]*Value{
"pause": makeNativeFunction(pauseFn),
"print": makeNativeFunction(printFn),
"sleep": makeNativeFunction(sleepFn),
Expand All @@ -17,7 +17,7 @@ var nativeFunctions = map[string]ConcreteValue{
}

type callable interface {
call(args []Value, ctx *Context)
call(args []*Value, ctx *Context)
}

type NativeFunction struct {
Expand All @@ -29,7 +29,7 @@ type RuntimeFunction struct {
instructions []Instruction
}

func makeNativeFunction(fn interface{}) ConcreteValue {
func makeNativeFunction(fn interface{}) *Value {
t := reflect.TypeOf(fn)
if t.Kind() != reflect.Func {
panic(fmt.Errorf("cannot make native function from %s", t.Kind()))
Expand Down Expand Up @@ -67,7 +67,7 @@ func kindFromType(t reflect.Type) Kind {
panic(fmt.Errorf("invalid value kind: %s", k.String()))
}

func (f NativeFunction) call(args []Value, ctx *Context) {
func (f NativeFunction) call(args []*Value, ctx *Context) {
in := make([]reflect.Value, len(args))
for i, a := range args {
in[i] = reflect.ValueOf(a.Resolve(ctx).value)
Expand All @@ -76,14 +76,14 @@ func (f NativeFunction) call(args []Value, ctx *Context) {
f.rawFn.Call(in)
}

func NewRuntimeFunction(paramNames []string, instructions []Instruction) RuntimeFunction {
return RuntimeFunction{
func NewRuntimeFunction(paramNames []string, instructions []Instruction) *RuntimeFunction {
return &RuntimeFunction{
paramNames: paramNames,
instructions: instructions,
}
}

func (f RuntimeFunction) call(args []Value, ctx *Context) {
func (f RuntimeFunction) call(args []*Value, ctx *Context) {
// Set all argument values in context.
funcCtx := NewContext(ctx)
for i, v := range args {
Expand Down
8 changes: 4 additions & 4 deletions internal/runtime/instructions.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ type Instruction interface {

type FunctionCall struct {
fn callable
args []Value
args []*Value
}

func NewFunctionCall(fn callable, args []Value) FunctionCall {
func NewFunctionCall(fn callable, args []*Value) FunctionCall {
return FunctionCall{
fn: fn,
args: args,
Expand All @@ -22,10 +22,10 @@ func (f FunctionCall) Execute(ctx *Context) {

type Assignment struct {
name string
val Value
val *Value
}

func NewAssignment(name string, val Value) Assignment {
func NewAssignment(name string, val *Value) Assignment {
return Assignment{
name: name,
val: val,
Expand Down
77 changes: 34 additions & 43 deletions internal/runtime/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,46 +9,43 @@ const (
NumberKind Kind = "number"
AnyKind Kind = "any"
FunctionKind Kind = "function"
VariableKind Kind = "variable"
)

type Value interface {
Resolve(ctx *Context) ConcreteValue
}

type ConcreteValue struct {
type Value struct {
kind Kind
value interface{}

// Function-specific
// Function
paramKinds []Kind
variadic bool
native bool
}

func NewStringValue(val string) ConcreteValue {
return ConcreteValue{
func NewStringValue(val string) *Value {
return &Value{
kind: StringKind,
value: val,
}
}

func NewNumberValue(val int) ConcreteValue {
return ConcreteValue{
func NewNumberValue(val int) *Value {
return &Value{
kind: NumberKind,
value: val,
}
}

func NewFunctionValue(fn RuntimeFunction, paramKinds []Kind) ConcreteValue {
return ConcreteValue{
func NewFunctionValue(fn *RuntimeFunction, paramKinds []Kind) *Value {
return &Value{
kind: FunctionKind,
value: fn,
paramKinds: paramKinds,
}
}

func NewNativeFunctionValue(fn callable, paramKinds []Kind, variadic bool) ConcreteValue {
return ConcreteValue{
func NewNativeFunctionValue(fn callable, paramKinds []Kind, variadic bool) *Value {
return &Value{
kind: FunctionKind,
value: fn,
paramKinds: paramKinds,
Expand All @@ -57,32 +54,46 @@ func NewNativeFunctionValue(fn callable, paramKinds []Kind, variadic bool) Concr
}
}

func NewEmptyValue(kind Kind) ConcreteValue {
return ConcreteValue{
func NewEmptyValue(kind Kind) *Value {
return &Value{
kind: kind,
}
}

func (v ConcreteValue) Resolve(_ *Context) ConcreteValue {
func NewVariableValue(ref string) *Value {
return &Value{
kind: VariableKind,
value: ref,
}
}

func (v *Value) Resolve(ctx *Context) *Value {
if v.kind == VariableKind {
return ctx.GetValue(v.value.(string))
}
return v
}

func (v ConcreteValue) assertKind(expected Kind) {
func (v *Value) assertKind(expected Kind) {
if v.kind != expected {
panic(fmt.Errorf("expected %s, got %s", expected, v.kind))
}
}

func (v ConcreteValue) Kind() Kind {
func (v *Value) RawValue() interface{} {
return v.value
}

func (v *Value) Kind() Kind {
return v.kind
}

func (v ConcreteValue) ParamKinds() []Kind {
func (v *Value) ParamKinds() []Kind {
v.assertKind(FunctionKind)
return v.paramKinds
}

func (v ConcreteValue) ParamKind(index int) Kind {
func (v *Value) ParamKind(index int) Kind {
v.assertKind(FunctionKind)
clampedI := index
if index >= len(v.paramKinds) && v.variadic {
Expand All @@ -91,32 +102,12 @@ func (v ConcreteValue) ParamKind(index int) Kind {
return v.paramKinds[clampedI]
}

func (v ConcreteValue) Variadic() bool {
func (v *Value) Variadic() bool {
v.assertKind(FunctionKind)
return v.variadic
}

func (v ConcreteValue) call(args []Value, ctx *Context) {
func (v *Value) call(args []*Value, ctx *Context) {
v.assertKind(FunctionKind)
v.value.(callable).call(args, ctx)
}

// TODO: Merge VariableValue into ConcreteValue

type VariableValue struct {
ref string
}

func NewVariableValue(ref string) VariableValue {
return VariableValue{
ref: ref,
}
}

func (v VariableValue) Ref() string {
return v.ref
}

func (v VariableValue) Resolve(ctx *Context) ConcreteValue {
return ctx.GetValue(v.ref)
}

0 comments on commit ac6e8e6

Please sign in to comment.