Class: Omnium::Interpreter::Core

Inherits:
NodeVisitor show all
Includes:
Common
Defined in:
lib/omnium/interpreter/core.rb

Overview

The visitor pattern is used to traverse the AST. This class may be thought of as a ‘tree visitor’.

Defined Under Namespace

Classes: InterpreterError

Constant Summary

Constants included from Common

Common::NIL_VALUE_TOKENS, Common::PARAMETERISED_TOKENS, Common::RESERVED_KEYWORDS, Common::TOKENS, Common::VALUE_BASED_TOKENS

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Common

define_token_predicate_method, define_token_type_method, token_entity

Methods inherited from NodeVisitor

#visit

Constructor Details

#initialize(parser) ⇒ Core

Returns a new instance of Core.



14
15
16
17
18
# File 'lib/omnium/interpreter/core.rb', line 14

def initialize(parser)
  @parser = parser
  @symbol_table = {}
  @name = nil
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



12
13
14
# File 'lib/omnium/interpreter/core.rb', line 12

def name
  @name
end

#symbol_tableObject (readonly)

Returns the value of attribute symbol_table.



12
13
14
# File 'lib/omnium/interpreter/core.rb', line 12

def symbol_table
  @symbol_table
end

Instance Method Details

#interpretObject



20
21
22
23
# File 'lib/omnium/interpreter/core.rb', line 20

def interpret
  tree = @parser.parse
  visit(tree)
end

#visit_Assignment(node) ⇒ Object



48
49
50
# File 'lib/omnium/interpreter/core.rb', line 48

def visit_Assignment(node)
  symbol_table[node.left.name.intern] = visit(node.right)
end

#visit_BinaryOperator(node) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/omnium/interpreter/core.rb', line 66

def visit_BinaryOperator(node)
  @type = node.operator.type

  if plus?
    visit(node.left) + visit(node.right)
  elsif minus?
    visit(node.left) - visit(node.right)
  elsif multiply?
    visit(node.left) * visit(node.right)
  elsif divide?
    visit(node.left) / visit(node.right)
  end
end

#visit_Block(node) ⇒ Object



32
33
34
35
36
37
38
# File 'lib/omnium/interpreter/core.rb', line 32

def visit_Block(node)
  node.variable_declarations.each do |variable_declaration|
    visit(variable_declaration)
  end

  visit(node.compound_statement)
end

#visit_Compound(node) ⇒ Object



40
41
42
# File 'lib/omnium/interpreter/core.rb', line 40

def visit_Compound(node)
  node.children.each { |child| visit(child) }
end

#visit_DataType(node) ⇒ Object



58
59
60
# File 'lib/omnium/interpreter/core.rb', line 58

def visit_DataType(node)
  # noop
end

#visit_Identifier(node) ⇒ Object



52
53
54
55
56
# File 'lib/omnium/interpreter/core.rb', line 52

def visit_Identifier(node)
  symbol_table.fetch(node.name.intern)
rescue KeyError
  raise(InterpreterError, "Variable '#{node.name}' not found")
end

#visit_NoOperation(node) ⇒ Object



62
63
64
# File 'lib/omnium/interpreter/core.rb', line 62

def visit_NoOperation(node)
  # noop
end

#visit_Number(node) ⇒ Object



90
91
92
# File 'lib/omnium/interpreter/core.rb', line 90

def visit_Number(node)
  node.value
end

#visit_Program(node) ⇒ Object

concrete visitor operations below



27
28
29
30
# File 'lib/omnium/interpreter/core.rb', line 27

def visit_Program(node)
  @name = node.name
  visit(node.block)
end

#visit_UnaryOperator(node) ⇒ Object



80
81
82
83
84
85
86
87
88
# File 'lib/omnium/interpreter/core.rb', line 80

def visit_UnaryOperator(node)
  @type = node.operator.type

  if plus?
    +visit(node.operand)
  elsif minus?
    -visit(node.operand)
  end
end

#visit_VariableDeclaration(node) ⇒ Object



44
45
46
# File 'lib/omnium/interpreter/core.rb', line 44

def visit_VariableDeclaration(node)
  # noop
end