Skip to content

Commit

Permalink
Minor code improvements (#24)
Browse files Browse the repository at this point in the history
* chore: code cleaning

* docs: add installation script

* docs: update download script

* Update README.md
  • Loading branch information
silverhairs authored Jul 20, 2023
1 parent 2faf6d5 commit af814cf
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 49 deletions.
4 changes: 2 additions & 2 deletions glox/cmd/glox.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package cmd
import (
"bufio"
"fmt"
"glox/errors"
"glox/exception"
"glox/interpreter"
"glox/lexer"
"glox/parser"
Expand All @@ -16,7 +16,7 @@ const PROMPT = ">> "
func RunFile(path string) error {
file, err := os.Open(path)
if err != nil {
return errors.New(0, path, err.Error())
return exception.Generic(0, path, err.Error())
}
defer file.Close()

Expand Down
24 changes: 0 additions & 24 deletions glox/errors/errors.go

This file was deleted.

19 changes: 19 additions & 0 deletions glox/exception/exception.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package exception

import (
"fmt"
)

func Generic(line int, where string, msg string) error {
message := fmt.Sprintf("%s @ %s", msg, where)
return fmt.Errorf("GloxGenericException([line %d] Error: %s)", line, message)
}

// Calls `e.New` with an empty string for the `where` argument.
func Short(line int, msg string) error {
return Generic(line, "", msg)
}

func Runtime(body any, message string) error {
return fmt.Errorf("RuntimeException(%+v, %s)", body, message)
}
68 changes: 53 additions & 15 deletions glox/interpreter/interpreter.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package interpreter

import (
"fmt"
"glox/ast"
"glox/exception"
"glox/token"
"math"
)
Expand Down Expand Up @@ -31,7 +33,9 @@ func (i *Interpreter) VisitUnary(exp *ast.Unary) any {
case token.BANG:
return !isTruthy(right)
case token.MINUS:
return -right.(float64)
num := panicWhenOperandIsNotNumber(exp.Operator, right)
return -num

}

return nil
Expand All @@ -43,39 +47,52 @@ func (i *Interpreter) VisitBinary(exp *ast.Binary) any {

switch exp.Operator.Type {
case token.GREATER:
return left.(float64) > right.(float64)
leftNum := panicWhenOperandIsNotNumber(exp.Operator, left)
rightNum := panicWhenOperandIsNotNumber(exp.Operator, right)
return leftNum > rightNum
case token.GREATER_EQ:
return left.(float64) >= right.(float64)
leftNum := panicWhenOperandIsNotNumber(exp.Operator, left)
rightNum := panicWhenOperandIsNotNumber(exp.Operator, right)
return leftNum >= rightNum
case token.LESS:
return left.(float64) < right.(float64)
leftNum := panicWhenOperandIsNotNumber(exp.Operator, left)
rightNum := panicWhenOperandIsNotNumber(exp.Operator, right)
return leftNum < rightNum
case token.LESS_EQ:
return left.(float64) <= right.(float64)
leftNum := panicWhenOperandIsNotNumber(exp.Operator, left)
rightNum := panicWhenOperandIsNotNumber(exp.Operator, right)
return leftNum <= rightNum
case token.EQ_EQ:
return isEqual(left, right)
case token.BANG_EQ:
return !isEqual(left, right)
case token.MINUS:
return left.(float64) - right.(float64)
leftNum := panicWhenOperandIsNotNumber(exp.Operator, left)
rightNum := panicWhenOperandIsNotNumber(exp.Operator, right)
return leftNum - rightNum
case token.PLUS:
if leftNum, isLFloat := left.(float64); isLFloat {
rightNum, isRFloat := right.(float64)
if isRFloat {
return leftNum + rightNum
}
}

// String concatenation
if leftStr, isLStr := left.(string); isLStr {
rightStr, isRStr := right.(string)
if isRStr {
return leftStr + rightStr
} else if leftVal, isLeftStr := left.(string); isLeftStr {
if rightVal, isRightStr := right.(string); isRightStr {
return leftVal + rightVal
}
}

err := exception.Runtime(exp.Operator, "Both operands must be eihter numbers or strings.")
panic(err)

case token.SLASH:
return left.(float64) / right.(float64)
leftNum := panicWhenOperandIsNotNumber(exp.Operator, left)
rightNum := panicWhenOperandIsNotNumber(exp.Operator, right)
return leftNum / rightNum
case token.ASTERISK:
return left.(float64) * right.(float64)
leftNum := panicWhenOperandIsNotNumber(exp.Operator, left)
rightNum := panicWhenOperandIsNotNumber(exp.Operator, right)
return leftNum * rightNum
}

return nil
Expand Down Expand Up @@ -124,3 +141,24 @@ func isEqual(l any, r any) bool {

return l == r
}

func checkOperand(operator token.Token, operand any) (*float64, error) {
num, isNum := operand.(float64)
if !isNum {
return nil, exception.Runtime(
operator,
fmt.Sprintf("Operator %q only accepts number operands.", operator.Lexeme),
)
}

return &num, nil
}

func panicWhenOperandIsNotNumber(operator token.Token, operand any) float64 {
num, err := checkOperand(operator, operand)
if err != nil {
panic(err)
} else {
return *num
}
}
10 changes: 5 additions & 5 deletions glox/lexer/lexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package lexer

import (
"fmt"
"glox/errors"
"glox/exception"
"glox/token"
"strconv"
)
Expand Down Expand Up @@ -112,7 +112,7 @@ func (s *Lexer) lex() {
} else if isAlpha(char) {
s.identifier()
} else {
errors.Short(s.line, fmt.Sprintf("Unexpected character %q", char))
exception.Short(s.line, fmt.Sprintf("Unexpected character %q", char))
}
}
}
Expand Down Expand Up @@ -179,7 +179,7 @@ func (s *Lexer) string() {
}

if s.isAtEnd() {
errors.Short(s.line, "Please add a double-quote at the end of the string.")
exception.Short(s.line, "Please add a double-quote at the end of the string.")
return
}

Expand All @@ -204,7 +204,7 @@ func (s *Lexer) number() {
literal := s.Source[s.start:s.current]
value, err := strconv.ParseFloat(literal, 64)
if err != nil {
errors.Short(s.line, fmt.Sprintf("%q is an invalid %q", literal, token.NUMBER))
exception.Short(s.line, fmt.Sprintf("%q is an invalid %q", literal, token.NUMBER))
return
}
s.addToken(token.NUMBER, value)
Expand Down Expand Up @@ -258,7 +258,7 @@ func (s *Lexer) slash() {
literal := s.Source[s.start+2 : s.current-2]
s.addToken(token.COMMENT_B, literal)
} else {
errors.Short(s.line, "opened multi-line comment has not been closed.")
exception.Short(s.line, "opened multi-line comment has not been closed.")
}

} else {
Expand Down
6 changes: 3 additions & 3 deletions glox/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package parser

import (
"glox/ast"
"glox/errors"
"glox/exception"
"glox/token"
)

Expand Down Expand Up @@ -178,10 +178,10 @@ func (p *Parser) consume(tokType token.TokenType, message string) token.Token {

func captureError(tok token.Token, msg string) error {
if tok.Type == token.EOF {
return errors.New(tok.Line, " at end", msg)
return exception.Generic(tok.Line, " at end", msg)
}

return errors.New(tok.Line, "'"+tok.Lexeme+"'", msg)
return exception.Generic(tok.Line, "'"+tok.Lexeme+"'", msg)
}

// Discards tokens that might case cascaded errors
Expand Down

0 comments on commit af814cf

Please sign in to comment.