diff options
| author | Charlie Stanton <charlie@shtanton.xyz> | 2023-04-21 16:22:16 +0100 | 
|---|---|---|
| committer | Charlie Stanton <charlie@shtanton.xyz> | 2023-04-21 16:22:16 +0100 | 
| commit | 12c1d179f32c38a929fcc9adb326a9f44c8288ae (patch) | |
| tree | d685922ed93708cbaf01357a95989283a7b86443 /walk | |
| parent | 5d8582711936cae3c42f2645d0f304418b17fb7e (diff) | |
| download | stred-go-12c1d179f32c38a929fcc9adb326a9f44c8288ae.tar | |
Replaces the interfaces implementation of Atom with a tagged union based implementation
Diffstat (limited to 'walk')
| -rw-r--r-- | walk/walk.go | 150 | 
1 files changed, 115 insertions, 35 deletions
| diff --git a/walk/walk.go b/walk/walk.go index 490a6f2..949b6a2 100644 --- a/walk/walk.go +++ b/walk/walk.go @@ -50,7 +50,7 @@ const (  	MapEnd  )  func (value TerminalValue) Atomise(in []Atom) []Atom { -	return append(in, value) +	return append(in, NewAtomTerminal(value))  }  func (value TerminalValue) String() string {  	switch value { @@ -69,7 +69,7 @@ func (value TerminalValue) String() string {  type ValueNull struct {}  func (value ValueNull) Atomise(in []Atom) []Atom { -	return append(in, value) +	return append(in, NewAtomNull())  }  func (value ValueNull) String() string {  	return "null" @@ -77,7 +77,7 @@ func (value ValueNull) String() string {  type ValueBool bool  func (value ValueBool) Atomise(in []Atom) []Atom { -	return append(in, value) +	return append(in, NewAtomBool(bool(value)))  }  func (value ValueBool) String() string {  	if value { @@ -89,38 +89,113 @@ func (value ValueBool) String() string {  type ValueNumber float64  func (value ValueNumber) Atomise(in []Atom) []Atom { -	return append(in, value) +	return append(in, NewAtomNumber(float64(value)))  }  func (value ValueNumber) String() string {  	v := float64(value)  	return fmt.Sprintf("%f", v)  } -type StringTerminal struct {} -func (value StringTerminal) String() string { -	return "\"" -} - -type StringAtom rune -func (value StringAtom) String() string { -	return string(value) -} -  type ValueString string  func (value ValueString) Atomise(in []Atom) []Atom { -	in = append(in, StringTerminal{}) +	in = append(in, NewAtomStringTerminal())  	for _, char := range value { -		in = append(in, StringAtom(char)) +		in = append(in, NewAtomStringRune(char))  	} -	in = append(in, StringTerminal{}) +	in = append(in, NewAtomStringTerminal())  	return in  }  func (value ValueString) String() string {  	return fmt.Sprintf("\"%s\"", string(value))  } -type Atom interface { -	String() string +type AtomType int64 +const ( +	AtomNull AtomType = iota +	AtomBool +	AtomNumber +	AtomTerminal +	AtomStringTerminal +	AtomStringRune +) +type Atom struct { +	Typ AtomType +	data uint64 +} +func NewAtomNull() Atom { +	return Atom { +		Typ: AtomNull, +		data: 0, +	} +} +func NewAtomBool(v bool) Atom { +	if v { +		return Atom { +			Typ: AtomBool, +			data: 1, +		} +	} else { +		return Atom { +			Typ: AtomBool, +			data: 0, +		} +	} +} +func NewAtomNumber(v float64) Atom { +	return Atom { +		Typ: AtomNumber, +		data: math.Float64bits(v), +	} +} +func NewAtomTerminal(v TerminalValue) Atom { +	return Atom { +		Typ: AtomTerminal, +		data: uint64(v), +	} +} +func NewAtomStringTerminal() Atom { +	return Atom { +		Typ: AtomStringTerminal, +		data: 0, +	} +} +func NewAtomStringRune(v rune) Atom { +	return Atom { +		Typ: AtomStringRune, +		data: uint64(v), +	} +} +func (v Atom) String() string { +	switch v.Typ { +		case AtomNull: +			return "null" +		case AtomBool: +			if v.data == 0 { +				return "false" +			} +			return "true" +		case AtomNumber: +			return fmt.Sprintf("%v", math.Float64frombits(v.data)) +		case AtomTerminal: +			switch TerminalValue(v.data) { +				case MapBegin: +					return "{" +				case MapEnd: +					return "}" +				case ArrayBegin: +					return "[" +				case ArrayEnd: +					return "]" +				default: +					panic("Invalid terminal atom") +			} +		case AtomStringTerminal: +			return "\"" +		case AtomStringRune: +			return string(rune(v.data)) +		default: +			panic("Invalid atom type") +	}  }  type WalkValue interface { @@ -481,12 +556,12 @@ func Compound(in []Atom) (out []WalkValue, error error) {  	i := 0  	inString := false  	for _, atom := range in { -		switch atom.(type) { -			case TerminalValue, ValueNull, ValueBool, ValueNumber: +		switch atom.Typ { +			case AtomNull, AtomBool, AtomNumber, AtomTerminal:  				if !inString {  					numValues++  				} -			case StringTerminal: +			case AtomStringTerminal:  				if inString {  					numValues++  				} @@ -501,32 +576,37 @@ func Compound(in []Atom) (out []WalkValue, error error) {  		}  		atom := in[i]  		i++ -		switch v := atom.(type) { -			case TerminalValue, ValueNull, ValueBool, ValueNumber: -				out = append(out, v.(WalkValue)) +		switch atom.Typ { +			case AtomNull: +				out = append(out, ValueNull{})  				continue -			case StringAtom: +			case AtomBool: +				out = append(out, ValueBool(atom.data != 0)) +				continue +			case AtomNumber: +				out = append(out, ValueNumber(math.Float64frombits(atom.data))) +				continue +			case AtomTerminal: +				out = append(out, TerminalValue(atom.data)) +				continue +			case AtomStringRune:  				return nil, CompoundRuneOutsideString -			case StringTerminal: +			case AtomStringTerminal:  			default:  				return nil, CompoundUnknownAtom  		}  		// Handle string start  		var builder strings.Builder -		loop: for { +		for {  			if i >= len(in) {  				return nil, CompoundMissingEnd  			}  			atom := in[i]  			i++ -			switch v := atom.(type) { -				case StringTerminal: -					break loop -				case StringAtom, ValueNull, ValueBool, ValueNumber, TerminalValue: -					builder.WriteString(v.String()) -				default: -					return nil, CompoundInvalidStringAtom +			if atom.Typ == AtomStringTerminal { +				break  			} +			builder.WriteString(atom.String())  		}  		out = append(out, ValueString(builder.String()))  	} | 
