pycplus 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/bin/pycplus +1 -1
  3. data/lib/nodes.rb +33 -13
  4. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2fde7222ccd4137c44659d5df46a12bc2cb57facbb373c129d54af19596aeb93
4
- data.tar.gz: b86597ee3514507775c3a2be65e9fd8ed1f2778be48d276b45b99898e0ba8223
3
+ metadata.gz: 9ba4de43decc549bf60ae97669e59b7e8dc597897d9f9f943c9547e93f260880
4
+ data.tar.gz: a8e6c2e1815da2725a6f5af2841a6d9ff7db0bf5ec58fd6a05ccde637df12a96
5
5
  SHA512:
6
- metadata.gz: 1437d02dc107e13a85893882db8d325e42d46e62783eeb27c7c58cbf4ce08bc844103e011084a36686ed465fac755bb3e45f96b274e9df4788637fd64ae33bfc
7
- data.tar.gz: 03faa5bad0cd3ca3242d64e236995baa1d03337d68fe013d3152e6f2a82d74919c8311cd2d1c1361486a8ff55515134d7cd7c0e3be9931b9f72533160f6adb74
6
+ metadata.gz: 1fdf3493c38f21ed5d515f1b4ea4c80849913ac6a4b6398bc6000a27df445ffa8161222cc9115d9bae0162b06809dc5531576d5182e0525ca998f74ad3f6895d
7
+ data.tar.gz: d51d284dac74989f444902c43ff177e706daf2887bf4e6fd80aae0aa250c744d6b6f9d979d61862ecc8353195b12c91cfaeacec0a8e77cd7eb974c759aafa412
data/bin/pycplus CHANGED
@@ -7,7 +7,7 @@ require_relative '../lib/pcpparse'
7
7
 
8
8
  # Method to print gem version
9
9
  def print_version
10
- spec = Gem::Specification.load('../pycplus.gemspec')
10
+ spec = Gem.loaded_specs['pycplus']
11
11
  puts "#{spec.name} version #{spec.version}"
12
12
  end
13
13
 
data/lib/nodes.rb CHANGED
@@ -2,38 +2,51 @@
2
2
 
3
3
  require_relative 'STL.rb'
4
4
 
5
+ # Class to handle scopes when evaluating AST.
5
6
  class Scope
6
- attr_reader :identifiers,:parent_scope
7
+ attr_reader :identifiers,:parent_scope, :non_local_variables
7
8
  def initialize(parent_scope = nil)
8
9
  @identifiers = {}
10
+ @non_local_variables = []
9
11
  @parent_scope = parent_scope
10
12
  end
11
13
 
14
+ # Set variable in current scope
12
15
  def set_variable(name, op, expression)
16
+ if @non_local_variables.include?(name)
17
+ raise NameError, "local identifier #{name} referenced before assignment"
18
+ end
13
19
  if op == '='
14
20
  @identifiers[name] = expression
15
21
  else
16
- id_scope = get_scope(name)
17
- @identifiers[name] = get_identifier(name) if id_scope
22
+ unless @identifiers.has_key?(name)
23
+ raise NameError, "local identifier #{name} referenced before assignment"
24
+ end
18
25
  if op == '+='
19
- @identifiers[name] = 0 if !id_scope
20
26
  @identifiers[name] += expression
21
27
  else
22
- @identifiers[name] = 0 if !id_scope
23
28
  @identifiers[name] -= expression
24
29
  end
25
30
  end
26
31
  end
27
32
 
33
+ def set_non_local_variable(name)
34
+ unless @non_local_variables.include?(name) && is_function(name)
35
+ @non_local_variables.append(name)
36
+ end
37
+ end
38
+
39
+ # Get value of identifier in current or parent scope(s) if defined.
28
40
  def get_identifier(name)
29
41
  scope = get_scope(name)
30
42
  if scope
31
43
  return scope.identifiers[name]
32
44
  else
33
- raise NameError,"Identifier #{name} not defined."
45
+ raise NameError,"Identifier #{name} not defined in scope."
34
46
  end
35
47
  end
36
48
 
49
+ # Get first scope where identifier is defined.
37
50
  def get_scope(name)
38
51
  if @identifiers.has_key?(name)
39
52
  return self
@@ -42,17 +55,20 @@ class Scope
42
55
  end
43
56
  end
44
57
 
58
+ # Checks if a identifier is a function.
45
59
  def is_function?(name)
46
60
  scope = get_scope(name)
47
61
  id_value = scope.get_identifier(name) if scope
48
62
  return id_value.is_a?(Hash)
49
63
  end
50
64
 
65
+ # Set a function in current scope.
51
66
  def set_function(name, block, parameters)
52
67
  @identifiers[name] = {:parameters => parameters, :block => block}
53
68
  end
54
69
  end
55
70
 
71
+
56
72
  class BlockNode
57
73
  def initialize(statements = nil)
58
74
  @block = statements
@@ -102,10 +118,10 @@ class FunctioncallNode
102
118
  return result
103
119
  end
104
120
 
105
- def evaluate_block(parameters, block, scope)
106
- new_scope = Scope.new(scope)
121
+ def evaluate_block(parameters, block, current_scope, id_scope)
122
+ new_scope = Scope.new(id_scope)
107
123
  parameters.zip(@arguments).each do |parameter, argument|
108
- new_scope.set_variable(parameter, '=', argument.evaluate(scope))
124
+ new_scope.set_variable(parameter, '=', argument.evaluate(current_scope))
109
125
  end
110
126
 
111
127
  result = block.evaluate(new_scope)
@@ -135,7 +151,7 @@ class FunctioncallNode
135
151
  parameters = function[:parameters]
136
152
  block = function[:block]
137
153
  validate_arguments(parameters)
138
- evaluate_block(parameters, block, scope)
154
+ evaluate_block(parameters, block,scope,id_scope)
139
155
  end
140
156
  end
141
157
  end
@@ -274,9 +290,12 @@ class IdentifierNode < PrimitiveNode
274
290
  def evaluate(scope)
275
291
  if scope.is_function?(@value)
276
292
  raise SyntaxError, "Identifier #{@value} is assigned to a function. Please use correct syntax for function call."
277
- else
278
- return scope.get_identifier(@value)
279
293
  end
294
+ id_value = scope.get_identifier(@value)
295
+ unless scope.identifiers.has_key?(@value)
296
+ scope.set_non_local_variable(@value)
297
+ end
298
+ return id_value
280
299
  end
281
300
  end
282
301
 
@@ -287,4 +306,5 @@ class DigitNode < PrimitiveNode
287
306
  end
288
307
 
289
308
  class BoolNode < PrimitiveNode
290
- end
309
+ end
310
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pycplus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Johannes