Skip to content

Commit

Permalink
Merge pull request #4 from SealNTibbers/feature/IsDirtyFix
Browse files Browse the repository at this point in the history
Fixed isDirty problem
  • Loading branch information
Alexander Kasyanov authored Oct 18, 2019
2 parents 4a64966 + 88d2697 commit 0e5c3c5
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 22 deletions.
42 changes: 30 additions & 12 deletions evaluator/smalltalkEvaluator.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ func NewTestEvaluator() *Evaluator {
func TestEval(codeString string) treeNodes.SmalltalkObjectInterface {
evaluator := NewTestEvaluator()
programNode := parser.InitializeParserFor(codeString)
return evaluator.EvaluateProgramNode(programNode)
return evaluator.EvaluateProgram(programNode)
}

func TestEvalWithScope(codeString string, scope *treeNodes.Scope) treeNodes.SmalltalkObjectInterface {
evaluator := NewEvaluatorWithGlobalScope(scope)
programNode := parser.InitializeParserFor(codeString)
return evaluator.EvaluateProgramNode(programNode)
return evaluator.EvaluateProgram(programNode)
}

//real world API
Expand Down Expand Up @@ -60,15 +60,15 @@ func (e *Evaluator) GetGlobalScope() *treeNodes.Scope {
}

func (e *Evaluator) RunProgram(programString string) treeNodes.SmalltalkObjectInterface {
programNode, ok := e.programCache[programString]
_, ok := e.programCache[programString]
if !ok {
programNode = parser.InitializeParserFor(programString)
e.programCache[programString] = programNode
e.programCache[programString] = parser.InitializeParserFor(programString)
}
return e.EvaluateProgramNode(programNode)
evaluatorProgram := e.programCache[programString]
return e.EvaluateProgram(evaluatorProgram)
}

func (e *Evaluator) EvaluateProgramNode(programNode treeNodes.ProgramNodeInterface) treeNodes.SmalltalkObjectInterface {
func (e *Evaluator) EvaluateProgram(program treeNodes.ProgramNodeInterface) treeNodes.SmalltalkObjectInterface {
var result treeNodes.SmalltalkObjectInterface
var localScope *treeNodes.Scope
if e.workspaceScope != nil {
Expand All @@ -78,12 +78,11 @@ func (e *Evaluator) EvaluateProgramNode(programNode treeNodes.ProgramNodeInterfa
}
localScope.OuterScope = e.globalScope

if e.globalScope.IsDirty() || programNode.GetLastValue() == nil {
result = programNode.Eval(localScope)
programNode.SetLastValue(result)
e.globalScope.Clean()
if program.GetLastValue() == nil {
result = program.Eval(localScope)
program.SetLastValue(result)
} else {
result = programNode.GetLastValue()
result = program.GetLastValue()
}

return result
Expand Down Expand Up @@ -124,23 +123,42 @@ func (e *Evaluator) EvaluateToInterface(programString string) interface{} {
}
}

func (e *Evaluator) updateCache(variableName string) {
for _, evaluatorProgram := range e.programCache {
needsUpdate := false
for _, variable := range evaluatorProgram.GetVariables() {
if variable == variableName {
needsUpdate = true
}
}
if needsUpdate {
evaluatorProgram.SetLastValue(nil)
}
}
}

//scope-related delegations
func (e *Evaluator) SetVar(name string, value treeNodes.SmalltalkObjectInterface) treeNodes.SmalltalkObjectInterface {
e.updateCache(name)
return e.globalScope.SetVar(name, value)
}

func (e *Evaluator) SetStringVar(name string, value string) treeNodes.SmalltalkObjectInterface {
e.updateCache(name)
return e.globalScope.SetStringVar(name, value)
}

func (e *Evaluator) SetNumberVar(name string, value float64) treeNodes.SmalltalkObjectInterface {
e.updateCache(name)
return e.globalScope.SetNumberVar(name, value)
}

func (e *Evaluator) SetBoolVar(name string, value bool) treeNodes.SmalltalkObjectInterface {
e.updateCache(name)
return e.globalScope.SetBoolVar(name, value)
}

func (e *Evaluator) FindValueByName(name string) (treeNodes.SmalltalkObjectInterface, bool) {
e.updateCache(name)
return e.globalScope.FindValueByName(name)
}
33 changes: 33 additions & 0 deletions evaluator/smalltalkEvaluator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,39 @@ func TestGlobalScopeEvaluation(t *testing.T) {
testutils.ASSERT_FLOAT64_EQ(t, resultObject.(*treeNodes.SmalltalkNumber).GetValue(), 25)
}

func TestGlobalScopeWithChangingEvaluation(t *testing.T) {
var inputString string
var resultObject treeNodes.SmalltalkObjectInterface

globalScope := new(treeNodes.Scope).Initialize()
globalScope.SetVar("x", treeNodes.NewSmalltalkNumber(25))

evaluator := NewEvaluatorWithGlobalScope(globalScope)

inputString = `x+5`
resultObject = evaluator.RunProgram(inputString)
testutils.ASSERT_TRUE(t, resultObject.TypeOf() == treeNodes.NUMBER_OBJ)
testutils.ASSERT_FLOAT64_EQ(t, resultObject.(*treeNodes.SmalltalkNumber).GetValue(), 30)

inputString = `x+10`
resultObject = evaluator.RunProgram(inputString)
testutils.ASSERT_TRUE(t, resultObject.TypeOf() == treeNodes.NUMBER_OBJ)
testutils.ASSERT_FLOAT64_EQ(t, resultObject.(*treeNodes.SmalltalkNumber).GetValue(), 35)

evaluator.SetVar("x", treeNodes.NewSmalltalkNumber(5))

inputString = `x+5`
resultObject = evaluator.RunProgram(inputString)
testutils.ASSERT_TRUE(t, resultObject.TypeOf() == treeNodes.NUMBER_OBJ)
testutils.ASSERT_FLOAT64_EQ(t, resultObject.(*treeNodes.SmalltalkNumber).GetValue(), 10)

// This test should be fail, because we have logic problem with isDirty
inputString = `x+10`
resultObject = evaluator.RunProgram(inputString)
testutils.ASSERT_TRUE(t, resultObject.TypeOf() == treeNodes.NUMBER_OBJ)
testutils.ASSERT_FLOAT64_EQ(t, resultObject.(*treeNodes.SmalltalkNumber).GetValue(), 15)
}

func TestLocalScopeEvaluation(t *testing.T) {
var inputString1, inputString2 string
var result1, result2 int64
Expand Down
53 changes: 53 additions & 0 deletions treeNodes/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package treeNodes

import (
"github.com/SealNTibbers/GotalkInterpreter/scanner"
"sort"
)

type ProgramNodeInterface interface {
Expand All @@ -16,6 +17,7 @@ type ProgramNodeInterface interface {
Eval(scope *Scope) SmalltalkObjectInterface
GetLastValue() SmalltalkObjectInterface
SetLastValue(SmalltalkObjectInterface)
GetVariables() []string
}

type Node struct {
Expand Down Expand Up @@ -111,6 +113,15 @@ func (m *SequenceNode) SetRightBar(rightBar int64) {
m.rightBar = rightBar
}

func (m *SequenceNode) GetVariables() []string {
result := [] string {}
for _, statement := range m.statements {
result = append(result, statement.GetVariables()...)
}
sort.Strings(result)
return result
}

type ValueNodeInterface interface {
ProgramNodeInterface
AddParenthesis(interval Interval)
Expand Down Expand Up @@ -159,6 +170,10 @@ func (a *AssignmentNode) IsAssignment() bool {
return true
}

func (a *AssignmentNode) GetVariables() []string {
return nil
}

type LiteralNodeInterface interface {
ValueNodeInterface
LiteralToken(token scanner.LiteralTokenInterface) LiteralNodeInterface
Expand Down Expand Up @@ -227,6 +242,10 @@ func (l *LiteralArrayNode) GetValue() string {
return value
}

func (m *LiteralArrayNode) GetVariables() []string {
return nil
}

type LiteralValueNode struct {
*LiteralNode
token scanner.LiteralTokenInterface
Expand All @@ -240,6 +259,10 @@ func (literalValue *LiteralValueNode) GetValue() string {
return literalValue.token.ValueOfToken()
}

func (l *LiteralValueNode) GetVariables() []string {
return nil
}

type VariableNode struct {
*ValueNode
Token scanner.ValueTokenInterface
Expand All @@ -249,6 +272,11 @@ func (v *VariableNode) GetName() string {
return v.Token.ValueOfToken()
}

func (m *VariableNode) GetVariables() []string {
result := [] string {}
return append(result,m.Token.ValueOfToken())
}

type NodeWithRreceiverInterface interface {
GetReceiver() ValueNodeInterface
}
Expand Down Expand Up @@ -303,6 +331,15 @@ func (m *MessageNode) SetArguments(arguments []ValueNodeInterface) {
}
}

func (m *MessageNode) GetVariables() []string {
variables := m.receiver.GetVariables()
for _, arg := range m.arguments {
variables = append(variables, arg.GetVariables()...)
}
sort.Strings(variables)
return variables
}

type CascadeNode struct {
*ValueNode
semicolons []int64
Expand All @@ -324,6 +361,10 @@ func (m *CascadeNode) SetMessages(messages []*MessageNode) {
}
}

func (m *CascadeNode) GetVariables() []string {
return nil
}

type BlockNode struct {
*ValueNode
bar int64
Expand Down Expand Up @@ -365,6 +406,18 @@ func (m *BlockNode) SetRight(right int64) {
m.right = right
}

func (m *BlockNode) GetVariables() []string {
result := m.body.GetVariables()
sort.Strings(result)
for _, arg := range m.arguments {
localVariable := arg.GetVariables()[0]
index := sort.SearchStrings(result,localVariable)
result = append(result[:index], result[index+1:]...)
}
sort.Strings(result)
return result
}

type Interval struct {
start int64
stop int64
Expand Down
10 changes: 0 additions & 10 deletions treeNodes/nodesEvaluation.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,6 @@ import (
type Scope struct {
variables map[string]SmalltalkObjectInterface
OuterScope *Scope
isDirty bool
}

func (s *Scope) IsDirty() bool {
return s.isDirty
}

func (s *Scope) Clean() {
s.isDirty = false
}

func (s *Scope) Initialize() *Scope {
Expand All @@ -26,7 +17,6 @@ func (s *Scope) Initialize() *Scope {
}

func (s *Scope) SetVar(name string, value SmalltalkObjectInterface) SmalltalkObjectInterface {
s.isDirty = true
s.variables[name] = value
return value
}
Expand Down

0 comments on commit 0e5c3c5

Please sign in to comment.