Improve code quality

This commit is contained in:
Neemek 2025-03-16 21:16:12 +01:00
parent 5edad332cd
commit 3f260e7ffd
Signed by: neemek
GPG key ID: 28360A8951CD0E9B
11 changed files with 95 additions and 45 deletions

View file

@ -78,7 +78,10 @@ func TestAll(t *testing.T) {
c := NewCompiler()
t.Log("Compiling parse tree")
c.Compile(tree)
err = c.Compile(tree)
if err != nil {
t.Fatalf("Compiler had an error: %s", err)
}
printChunk(t, name, c.Chunk)
@ -108,7 +111,7 @@ func BenchmarkAll(b *testing.B) {
tree, _ := p.Parse()
c := NewCompiler()
c.Compile(tree)
_ = c.Compile(tree)
vm := NewVM(c.Chunk, 256, 256)

View file

@ -92,7 +92,10 @@ func (c *Compiler) Compile(tree Node) error {
c.addConstant(v)
} else {
for _, n := range l.items {
c.Compile(n)
err := c.Compile(n)
if err != nil {
return err
}
}
c.add(InstructionFormList)
c.addU16(uint16(len(l.items)))
@ -102,7 +105,10 @@ func (c *Compiler) Compile(tree Node) error {
c.getVar(tree.(*ReferenceNode).name)
case BinaryNodeType:
c.compileBinary(tree.(*BinaryNode))
err := c.compileBinary(tree.(*BinaryNode))
if err != nil {
return err
}
case BooleanNodeType:
if tree.(*BooleanNode).value {
@ -117,7 +123,10 @@ func (c *Compiler) Compile(tree Node) error {
case BlockNodeType:
c.descend()
for _, n := range tree.(*BlockNode).statements {
c.Compile(n)
err := c.Compile(n)
if err != nil {
return err
}
}
c.ascend()
@ -125,7 +134,10 @@ func (c *Compiler) Compile(tree Node) error {
n := tree.(*ConditionalNode)
// the stack should have whether the condition was truthful
c.Compile(n.condition)
err := c.Compile(n.condition)
if err != nil {
return err
}
// if the condition equated to true, we should jump over the body
c.add(InstructionJumpFalse)
@ -135,7 +147,10 @@ func (c *Compiler) Compile(tree Node) error {
c.advance(2)
// this part would be executed if the value was true
c.Compile(n.do)
err = c.Compile(n.do)
if err != nil {
return err
}
// we store the position of the jump over the else code here
var jumpOverElse Pos
@ -150,7 +165,10 @@ func (c *Compiler) Compile(tree Node) error {
c.putU16(jumpByPos, uint16(c.ip-jumpByPos-2))
if n.otherwise != nil {
c.Compile(n.otherwise)
err := c.Compile(n.otherwise)
if err != nil {
return err
}
c.putU16(jumpOverElse, uint16(c.ip-jumpOverElse-2))
}
@ -158,13 +176,19 @@ func (c *Compiler) Compile(tree Node) error {
n := tree.(*LoopNode)
conditionPos := c.ip
c.Compile(n.condition)
err := c.Compile(n.condition)
if err != nil {
return err
}
c.add(InstructionJumpFalse)
jumpValuePos := c.ip
c.advance(2)
c.Compile(n.do)
err = c.Compile(n.do)
if err != nil {
return err
}
c.add(InstructionLoop)
// condition pos < ip
@ -177,20 +201,32 @@ func (c *Compiler) Compile(tree Node) error {
if n.name == "_" {
// allow non-ish statements
c.Compile(n.value)
err := c.Compile(n.value)
if err != nil {
return err
}
c.add(InstructionPop)
} else {
c.setVar(n.name, n.value, n.declare)
err := c.setVar(n.name, n.value, n.declare)
if err != nil {
return err
}
}
case CallNodeType:
n := tree.(*CallNode)
for _, arg := range n.args {
c.Compile(arg)
err := c.Compile(arg)
if err != nil {
return err
}
}
c.Compile(n.source)
err := c.Compile(n.source)
if err != nil {
return err
}
c.add(InstructionCall)

View file

@ -117,7 +117,7 @@ func GetCompileTestData() map[string]CompileTestData {
},
},
},
"conditional_welse_false": {
"conditional_else_false": {
&BlockNode{
[]Node{
&AssignNode{
@ -164,7 +164,7 @@ func GetCompileTestData() map[string]CompileTestData {
},
},
},
"conditional_welse_true": {
"conditional_else_true": {
&BlockNode{
[]Node{
&AssignNode{
@ -363,7 +363,10 @@ func TestCompile(t *testing.T) {
c := NewCompiler()
t.Log("Compiling node tree")
c.Compile(testCase.tree)
err := c.Compile(testCase.tree)
if err != nil {
t.Fatalf("Compiling failed: %v", err)
}
t.Log("Initializing vm")
vm := NewVM(c.Chunk, 256, 256)
@ -387,7 +390,7 @@ func BenchmarkCompile(b *testing.B) {
b.Run(name, func(b *testing.B) {
for i := 0; i < b.N; i++ {
c := NewCompiler()
c.Compile(testCase.tree)
_ = c.Compile(testCase.tree)
}
})
}
@ -426,16 +429,15 @@ func TestCompiler_CleanStack(t *testing.T) {
}
// clean statements
case BlockNodeType:
case ConditionalNodeType:
case LoopNodeType:
case AssignNodeType:
case FunctionNodeType:
default:
}
t.Run(name, func(t *testing.T) {
c := NewCompiler()
c.Compile(tc.tree)
err := c.Compile(tc.tree)
if err != nil {
t.Fatalf("Compiling failed: %v", err)
}
vm := NewVM(c.Chunk, 256, 256)
for vm.Next() {

View file

@ -193,7 +193,7 @@ func (l *Lexer) NextToken() (Token, error) {
l.start = l.current
var c = []rune(l.src)[l.current]
var c = l.src[l.current]
l.advance()
switch c {

View file

@ -182,14 +182,14 @@ func TestNewLexer(t *testing.T) {
// lexer NextToken provides an error when it comes across an invalid token
func TestLexer_NextTokenErrors(t *testing.T) {
invalid_codes := []string{
invalidCodes := []string{
// Invalid tokens
"^", "@", "$&", "¨",
// Non-ending string (in same line)
"\"", "Hini minit \"mini moe", "\"this is some test\ncontent\"", "\n\"Hello world",
}
for _, code := range invalid_codes {
for _, code := range invalidCodes {
lex := NewLexer(code)
tok, err := lex.NextToken()

View file

@ -237,7 +237,7 @@ func (n NilNode) String() string {
return "nil"
}
// block node with statements
// BlockNode block node with statements
type BlockNode struct {
statements []Node
}
@ -284,7 +284,7 @@ func (n ConditionalNode) String() string {
return fmt.Sprintf("if %s then %s otheriwise %s", n.condition.String(), n.do.String(), n.otherwise.String())
}
// Loops (for/while)
// LoopNode Loops (for/while)
type LoopNode struct {
condition Node
do Node
@ -298,7 +298,7 @@ func (n LoopNode) String() string {
return fmt.Sprintf("while %s loop %s", n.condition.String(), n.do.String())
}
// assignment
// AssignNode assignment
type AssignNode struct {
name string
value Node
@ -313,7 +313,7 @@ func (n AssignNode) String() string {
return fmt.Sprintf("set %s to %s", n.name, n.value)
}
// function call
// CallNode function call
type CallNode struct {
source Node
args []Node
@ -328,7 +328,7 @@ func (n CallNode) String() string {
return fmt.Sprintf("call %s with args (%s)", n.source.String(), n.args)
}
// definition of function
// FunctionNode definition of function
type FunctionNode struct {
name string
params []string

View file

@ -17,7 +17,7 @@ func (p *ParsingError) Error() string {
return p.Description
}
// Print a rich and informative error
// Format Print a rich and informative error
func (p *ParsingError) Format(src []rune) string {
builder := strings.Builder{}

View file

@ -667,9 +667,9 @@ func NodeEquality(t *testing.T, n1 Node, n2 Node) {
func TestParser_Parse(t *testing.T) {
t.Logf("Getting test data")
token_data := GetTokenTestData()
tokenData := GetTokenTestData()
for name, data := range token_data {
for name, data := range tokenData {
if name != "empty_block" && name != "lambda" {
continue
}
@ -692,9 +692,9 @@ func TestParser_Parse(t *testing.T) {
}
func BenchmarkParser_Parse(b *testing.B) {
token_data := GetTokenTestData()
tokenData := GetTokenTestData()
for name, data := range token_data {
for name, data := range tokenData {
b.Run(name, func(b *testing.B) {
for i := 0; i < b.N; i++ {
p := NewParser(data.tokens)

View file

@ -154,7 +154,7 @@ func (v *BoolValue) Equals(other Value) bool {
return other.Type() == BoolValueType && other.(*BoolValue).bool == v.bool
}
func (v *BoolValue) Get(key string) (Value, error) {
func (v *BoolValue) Get(_ string) (Value, error) {
return nil, errors.New("booleans have no properties")
}
@ -254,7 +254,7 @@ func (v *NumberValue) Equals(other Value) bool {
return other.Type() == NumberValueType && other.(*NumberValue).float64 == v.float64
}
func (v *NumberValue) Get(key string) (Value, error) {
func (v *NumberValue) Get(_ string) (Value, error) {
// TODO maybe add standard functions for number values?
return nil, errors.New("numbers have no properties")
}
@ -489,7 +489,7 @@ type BuiltinFunctionValue struct {
Parent Value
}
func (v BuiltinFunctionValue) Type() ValueType {
func (v *BuiltinFunctionValue) Type() ValueType {
return BuiltinFunctionValueType
}