Skip to content

Commit

Permalink
init: eval step; fix repel
Browse files Browse the repository at this point in the history
  • Loading branch information
Houcine EL ADDALI committed Dec 18, 2023
1 parent 97fa1e4 commit 136dab7
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 6 deletions.
20 changes: 14 additions & 6 deletions cmd/REPL/repel.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/houcine7/JIPL/internal/lexer"
"github.com/houcine7/JIPL/internal/parser"
"github.com/houcine7/JIPL/internal/runtime"
)

// REPL :Read --> Evaluate --> Print --> loop
Expand All @@ -18,14 +19,20 @@ import (
* To interact with the user via terminal
*/

const PROMPT = ">"
const PROMPT = "🟢>"

func Start(in io.Reader, out io.Writer) {
scanner := bufio.NewScanner(in)

fmt.Println(" ********** ")
fmt.Println("------------- Welcome to JIPL REPL ------------")
fmt.Println(" ********** ")
fmt.Println(` _ _____ _____ _
| |_ _| __ \| |
| | | | | |__) | |
_ | | | | | ___/| |
| |__| |_| |_| | | |____
\____/|_____|_| |______|
`)
fmt.Println("------------- Welcome to JIPL: you can begin coding now ------------")
fmt.Println(" 👋 ")

for {
fmt.Print(PROMPT)
Expand All @@ -46,14 +53,15 @@ func Start(in io.Reader, out io.Writer) {
errs := repParser.Errors()

if len(errs) != 0 {
io.WriteString(out, fmt.Sprintf("%d errors ❌ occurred while parsing your input \n", len(errs)))
io.WriteString(out, fmt.Sprintf("%d errors ❌ occurred while parsing your input \n", len(errs)))
for idx, e := range errs {
io.WriteString(out, fmt.Sprintf("error number:%d with message: %s \n", idx, e))
}
continue
}

io.WriteString(out, pr.ToString())
evaluated := runtime.Eval(pr)
io.WriteString(out, evaluated.ToString())
io.WriteString(out, "\n")

}
Expand Down
31 changes: 31 additions & 0 deletions internal/runtime/eval.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package runtime

import (
ast "github.com/houcine7/JIPL/internal/AST"
"github.com/houcine7/JIPL/internal/types"
)

func Eval(node ast.Node) types.ObjectJIPL {
switch node := node.(type) {
case *ast.Program:
return evalAllStatements(node.Statements)
case *ast.ExpressionStatement:
return Eval(node.Expression)
case *ast.IntegerLiteral:
return &types.Integer{Val: node.Value}
case *ast.BooleanExp:
return &types.Boolean{Val: node.Value}
default:
return nil
}
}

func evalAllStatements(stms []ast.Statement) types.ObjectJIPL {
var resrult types.ObjectJIPL

for _, stm := range stms {
resrult = Eval(stm)
}

return resrult
}
43 changes: 43 additions & 0 deletions internal/runtime/eval_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package runtime

import (
"testing"

"github.com/houcine7/JIPL/internal/lexer"
"github.com/houcine7/JIPL/internal/parser"
"github.com/houcine7/JIPL/internal/types"
)

func TestIntegerEval(t *testing.T) {
testData := []struct {
input string
expected int
}{
{"4545;", 4545},
{"7;", 7},
}

for _, test := range testData {
evaluated := getEvaluated(test.input)
testIntegerObject(t, evaluated, test.expected)
}
}

func getEvaluated(input string) types.ObjectJIPL {
l := lexer.InitLexer(input)
p := parser.InitParser(l)
program := p.Parse()
return Eval(program)
}

func testIntegerObject(t *testing.T, obj types.ObjectJIPL, expected int) {
intObj, ok := obj.(*types.Integer)
if !ok {
t.Fatalf("the obj is not of type types.Integer, instead got %T",
obj,
)
}
if intObj.Val != expected {
t.Fatalf("the value of the integer object is not valid expected :%d and got %d", expected, intObj.Val)
}
}
52 changes: 52 additions & 0 deletions internal/types/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package types

import "fmt"

type TypeObj string

type ObjectJIPL interface {
GetType() TypeObj
ToString() string
}

type Integer struct {
Val int
}

type Boolean struct {
Val bool
}

type Undefined struct{}

// implementing OBjectJIPL interface by supporeted types
func (und *Undefined) ToString() string {
return "undefined"
}

func (und *Undefined) GetType() TypeObj {
return T_UNDEFINED
}

func (boolObj *Boolean) ToString() string {
return fmt.Sprintf("%t", boolObj.Val)
}

func (boolObj *Boolean) GetType() TypeObj {
return T_BOOLEAN
}

func (intObj *Integer) ToString() string {
return fmt.Sprintf("%d", intObj.Val)
}

func (intObj *Integer) GetType() TypeObj {
return T_ITNTEGER
}

// cte of types
const (
T_ITNTEGER = "INTEGER"
T_BOOLEAN = "BOOLEAN"
T_UNDEFINED = "UNDEFINED"
)

0 comments on commit 136dab7

Please sign in to comment.