gisele 0.0.1 → 0.1.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 (58) hide show
  1. data/CHANGELOG.md +39 -1
  2. data/gisele.noespec +1 -1
  3. data/lib/gisele/command.rb +13 -4
  4. data/lib/gisele/errors.rb +21 -0
  5. data/lib/gisele/language/ast/helpers.rb +37 -0
  6. data/lib/gisele/language/ast/node.rb +54 -0
  7. data/lib/gisele/language/ast/unit.rb +10 -0
  8. data/lib/gisele/language/ast.rb +14 -0
  9. data/lib/gisele/language/sugar_removal.rb +53 -0
  10. data/lib/gisele/language/syntax/bool_and.rb +14 -0
  11. data/lib/gisele/language/syntax/bool_lit.rb +14 -0
  12. data/lib/gisele/language/syntax/bool_not.rb +14 -0
  13. data/lib/gisele/language/syntax/bool_or.rb +14 -0
  14. data/lib/gisele/language/syntax/bool_paren.rb +14 -0
  15. data/lib/gisele/language/syntax/else_clause.rb +14 -0
  16. data/lib/gisele/language/syntax/elsif_clause.rb +16 -0
  17. data/lib/gisele/language/syntax/event_set.rb +15 -0
  18. data/lib/gisele/language/syntax/fluent_def.rb +18 -0
  19. data/lib/gisele/language/syntax/grammar.citrus +202 -0
  20. data/lib/gisele/language/syntax/if_st.rb +18 -0
  21. data/lib/gisele/language/syntax/implicit_seq_st.rb +16 -0
  22. data/lib/gisele/language/syntax/node.rb +35 -0
  23. data/lib/gisele/language/syntax/par_st.rb +14 -0
  24. data/lib/gisele/language/syntax/seq_st.rb +14 -0
  25. data/lib/gisele/language/syntax/st_list.rb +14 -0
  26. data/lib/gisele/language/syntax/task_call_st.rb +14 -0
  27. data/lib/gisele/language/syntax/task_def.rb +17 -0
  28. data/lib/gisele/language/syntax/task_refinement.rb +15 -0
  29. data/lib/gisele/language/syntax/task_signature.rb +15 -0
  30. data/lib/gisele/language/syntax/trackvar_def.rb +19 -0
  31. data/lib/gisele/language/syntax/unit.rb +14 -0
  32. data/lib/gisele/language/syntax/var_ref.rb +14 -0
  33. data/lib/gisele/language/syntax/while_st.rb +16 -0
  34. data/lib/gisele/language/syntax.rb +29 -0
  35. data/lib/gisele/language/transformer.rb +38 -0
  36. data/lib/gisele/language.rb +15 -1
  37. data/lib/gisele/version.rb +2 -2
  38. data/lib/gisele.rb +7 -1
  39. data/spec/command/main/gisele_ast_ruby.stdout +38 -28
  40. data/spec/command/main/gisele_help.stdout +5 -0
  41. data/spec/command/main/gisele_no_sugar.cmd +1 -0
  42. data/spec/command/main/gisele_no_sugar.stdout +61 -0
  43. data/spec/fixtures/tasks/simple.ast +18 -14
  44. data/spec/fixtures/tasks/simple.gis +2 -0
  45. data/spec/spec_helper.rb +3 -3
  46. data/spec/test_examples.rb +3 -3
  47. data/spec/unit/language/ast/test_node.rb +61 -0
  48. data/spec/unit/language/sugar_removal/test_if_to_guarded_commands.rb +90 -0
  49. data/spec/unit/language/{test_grammar.rb → syntax/test_grammar.rb} +18 -30
  50. data/spec/unit/language/syntax/test_to_ast.rb +245 -0
  51. data/spec/unit/language/test_ast.rb +21 -247
  52. data/spec/unit/language/test_syntax.rb +48 -0
  53. data/spec/unit/language/test_transformer.rb +68 -0
  54. data/spec/unit/test_language.rb +35 -0
  55. metadata +69 -25
  56. data/lib/gisele/language/grammar.citrus +0 -246
  57. data/lib/gisele/language/parser.rb +0 -30
  58. data/spec/unit/language/test_parser.rb +0 -27
@@ -0,0 +1,35 @@
1
+ module Gisele
2
+ module Language
3
+ module Syntax
4
+ module Node
5
+
6
+ def to_ast
7
+ Language::AST.node(_to_ast)
8
+ end
9
+
10
+ end # module Node
11
+ end # module Syntax
12
+ end # module Language
13
+ end # module Gisele
14
+ require_relative 'event_set'
15
+ require_relative 'fluent_def'
16
+ require_relative 'trackvar_def'
17
+ require_relative 'var_ref'
18
+ require_relative 'bool_lit'
19
+ require_relative 'bool_paren'
20
+ require_relative 'bool_not'
21
+ require_relative 'bool_and'
22
+ require_relative 'bool_or'
23
+ require_relative 'st_list'
24
+ require_relative 'implicit_seq_st'
25
+ require_relative 'task_call_st'
26
+ require_relative 'seq_st'
27
+ require_relative 'par_st'
28
+ require_relative 'while_st'
29
+ require_relative 'if_st'
30
+ require_relative 'else_clause'
31
+ require_relative 'elsif_clause'
32
+ require_relative 'task_refinement'
33
+ require_relative 'task_signature'
34
+ require_relative 'task_def'
35
+ require_relative 'unit'
@@ -0,0 +1,14 @@
1
+ module Gisele
2
+ module Language
3
+ module Syntax
4
+ module ParSt
5
+ include Node
6
+
7
+ def _to_ast
8
+ [:par_st] + captures[:st_list].first.value
9
+ end
10
+
11
+ end # module ParSt
12
+ end # module Syntax
13
+ end # module Language
14
+ end # module Gisele
@@ -0,0 +1,14 @@
1
+ module Gisele
2
+ module Language
3
+ module Syntax
4
+ module SeqSt
5
+ include Node
6
+
7
+ def _to_ast
8
+ [:seq_st] + captures[:st_list].first.value
9
+ end
10
+
11
+ end # module SeqSt
12
+ end # module Syntax
13
+ end # module Language
14
+ end # module Gisele
@@ -0,0 +1,14 @@
1
+ module Gisele
2
+ module Language
3
+ module Syntax
4
+ module StList
5
+ include Node
6
+
7
+ def value
8
+ captures[:explicit_statement].map{|x| x.to_ast}
9
+ end
10
+
11
+ end # module StList
12
+ end # module Syntax
13
+ end # module Language
14
+ end # module Gisele
@@ -0,0 +1,14 @@
1
+ module Gisele
2
+ module Language
3
+ module Syntax
4
+ module TaskCallSt
5
+ include Node
6
+
7
+ def _to_ast
8
+ [:task_call_st, strip]
9
+ end
10
+
11
+ end # module TaskCallSt
12
+ end # module Syntax
13
+ end # module Language
14
+ end # module Gisele
@@ -0,0 +1,17 @@
1
+ module Gisele
2
+ module Language
3
+ module Syntax
4
+ module TaskDef
5
+ include Node
6
+
7
+ def _to_ast
8
+ name = captures[:task_name].first.strip
9
+ sig = captures[:task_signature].map{|x| x.to_ast}.first || [:task_signature]
10
+ ref = captures[:task_refinement].map{|x| x.to_ast}.first || [:task_refinement]
11
+ [:task_def, name, sig, ref]
12
+ end
13
+
14
+ end # module TaskDef
15
+ end # module Syntax
16
+ end # module Language
17
+ end # module Gisele
@@ -0,0 +1,15 @@
1
+ module Gisele
2
+ module Language
3
+ module Syntax
4
+ module TaskRefinement
5
+ include Node
6
+
7
+ def _to_ast
8
+ main = captures[:process_statement].first.to_ast
9
+ [:task_refinement, main]
10
+ end
11
+
12
+ end # module TaskRefinement
13
+ end # module Syntax
14
+ end # module Language
15
+ end # module Gisele
@@ -0,0 +1,15 @@
1
+ module Gisele
2
+ module Language
3
+ module Syntax
4
+ module TaskSignature
5
+ include Node
6
+
7
+ def _to_ast
8
+ list = captures[:task_signature_element].map{|x| x.to_ast}
9
+ [:task_signature] + list
10
+ end
11
+
12
+ end # module TaskSignature
13
+ end # module Syntax
14
+ end # module Language
15
+ end # module Gisele
@@ -0,0 +1,19 @@
1
+ module Gisele
2
+ module Language
3
+ module Syntax
4
+ module TrackvarDef
5
+ include Node
6
+
7
+ def _to_ast
8
+ name = captures[:variable_name].first.strip
9
+ init, term = captures[:event_set].map{|x| x.to_ast}
10
+ term = [:event_set] unless term
11
+ initval = captures[:initially_def].first
12
+ initval = (initval && !initval.empty?) ? initval.value : nil
13
+ [:trackvar, name, init, term, initval]
14
+ end
15
+
16
+ end # module TrackvarDef
17
+ end # module Syntax
18
+ end # module Language
19
+ end # module Gisele
@@ -0,0 +1,14 @@
1
+ module Gisele
2
+ module Language
3
+ module Syntax
4
+ module Unit
5
+ include Node
6
+
7
+ def _to_ast
8
+ [:unit] + captures[:task_def].map{|x| x.to_ast}
9
+ end
10
+
11
+ end # module Unit
12
+ end # module Syntax
13
+ end # module Language
14
+ end # module Gisele
@@ -0,0 +1,14 @@
1
+ module Gisele
2
+ module Language
3
+ module Syntax
4
+ module VarRef
5
+ include Node
6
+
7
+ def _to_ast
8
+ [:var_ref, strip]
9
+ end
10
+
11
+ end # module VarRef
12
+ end # module Syntax
13
+ end # module Language
14
+ end # module Gisele
@@ -0,0 +1,16 @@
1
+ module Gisele
2
+ module Language
3
+ module Syntax
4
+ module WhileSt
5
+ include Node
6
+
7
+ def _to_ast
8
+ cond = captures[:bool_expr].first.to_ast
9
+ dost = captures[:process_statement].first.to_ast
10
+ [:while_st, cond, dost]
11
+ end
12
+
13
+ end # module WhileSt
14
+ end # module Syntax
15
+ end # module Language
16
+ end # module Gisele
@@ -0,0 +1,29 @@
1
+ require_relative 'syntax/node'
2
+ module Gisele
3
+ module Language
4
+ module Syntax
5
+ Citrus.load(File.expand_path('../syntax/grammar', __FILE__))
6
+
7
+ def parse(input, options = {})
8
+ source = parsing_source(input)
9
+ Grammar.parse(source, options)
10
+ end
11
+ module_function :parse
12
+
13
+ def ast(input, parse_options = {})
14
+ parse(input, parse_options).to_ast
15
+ end
16
+ module_function :ast
17
+
18
+ private
19
+
20
+ def parsing_source(input)
21
+ input = File.read(input.to_path) if input.respond_to?(:to_path)
22
+ input = input.to_str if input.respond_to?(:to_str)
23
+ input
24
+ end
25
+ module_function :parsing_source
26
+
27
+ end # module Syntax
28
+ end # module Language
29
+ end # module Gisele
@@ -0,0 +1,38 @@
1
+ module Gisele
2
+ module Language
3
+ class Transformer
4
+ include AST::Helpers
5
+
6
+ def call(node)
7
+ node = pre_call(node)
8
+ meth = :"on_#{node.rule_name}"
9
+ meth = :"on_missing" unless respond_to?(meth)
10
+ post_call send(meth, node)
11
+ end
12
+
13
+ def on_missing(node)
14
+ raise UnexpectedNodeError, "Unexpected node: #{node.rule_name}"
15
+ end
16
+
17
+ protected
18
+
19
+ def pre_call(node)
20
+ unless looks_a_node?(node)
21
+ raise ArgumentError, "AST node expected, got #{node.inspect}", caller
22
+ end
23
+ node(node)
24
+ end
25
+
26
+ def post_call(transformed)
27
+ looks_a_node?(transformed) ? node(transformed) : transformed
28
+ end
29
+
30
+ def copy_and_applyall(node)
31
+ node.copy do |memo,child|
32
+ memo << (child.is_a?(AST::Node) ? call(child) : child)
33
+ end
34
+ end
35
+
36
+ end # class Transformer
37
+ end # module Language
38
+ end # module Gisele
@@ -1,6 +1,20 @@
1
1
  module Gisele
2
2
  module Language
3
3
 
4
+ def rule2mod(rule)
5
+ rule.to_s.gsub(/(^|_)([a-z])/){|x| $2.capitalize}.to_sym
6
+ end
7
+ module_function :rule2mod
8
+
9
+ def mod2rule(mod)
10
+ mod = mod.name.to_s.split('::').last.to_sym if mod.is_a?(Module)
11
+ mod.to_s.gsub(/[A-Z]/){|x| "_#{x.downcase}"}[1..-1].to_sym
12
+ end
13
+ module_function :mod2rule
14
+
4
15
  end # module Language
5
16
  end # module Gisele
6
- require_relative 'language/parser'
17
+ require_relative 'language/syntax'
18
+ require_relative 'language/ast'
19
+ require_relative 'language/transformer'
20
+ require_relative 'language/sugar_removal'
@@ -2,8 +2,8 @@ module Gisele
2
2
  module Version
3
3
 
4
4
  MAJOR = 0
5
- MINOR = 0
6
- TINY = 1
5
+ MINOR = 1
6
+ TINY = 0
7
7
 
8
8
  def self.to_s
9
9
  [ MAJOR, MINOR, TINY ].join('.')
data/lib/gisele.rb CHANGED
@@ -1,14 +1,20 @@
1
1
  require_relative "gisele/version"
2
2
  require_relative "gisele/loader"
3
+ require_relative 'gisele/errors'
3
4
  #
4
5
  # Gisele is a Process Analyzer Toolset
5
6
  #
6
7
  module Gisele
7
8
 
8
9
  def parse(input)
9
- Language::Parser::parse(input)
10
+ Language::Syntax::parse(input)
10
11
  end
11
12
  module_function :parse
12
13
 
14
+ def ast(input)
15
+ Language::Syntax::ast(input)
16
+ end
17
+ module_function :ast
18
+
13
19
  end # module Gisele
14
20
  require_relative 'gisele/language'
@@ -1,43 +1,53 @@
1
1
  [
2
- :task,
3
- "Simple",
2
+ :unit,
4
3
  [
5
- :signature,
4
+ :task_def,
5
+ "Simple",
6
6
  [
7
- :fluent,
8
- "diagKnown",
7
+ :task_signature,
9
8
  [
10
- :event_set,
11
- "Diagnosis:start"
12
- ],
13
- [
14
- :event_set,
15
- "Treatment:end"
16
- ],
17
- nil
18
- ]
19
- ],
20
- [
21
- :refinement,
9
+ :fluent,
10
+ "diagKnown",
11
+ [
12
+ :event_set,
13
+ "Diagnosis:start"
14
+ ],
15
+ [
16
+ :event_set,
17
+ "Treatment:end"
18
+ ],
19
+ nil
20
+ ]
21
+ ],
22
22
  [
23
- :seq,
23
+ :task_refinement,
24
24
  [
25
- :if,
25
+ :seq_st,
26
26
  [
27
- :not,
27
+ :if_st,
28
+ [
29
+ :bool_not,
30
+ [
31
+ :var_ref,
32
+ "diagKnown"
33
+ ]
34
+ ],
28
35
  [
29
- :varref,
30
- "diagKnown"
36
+ :task_call_st,
37
+ "Diagnosis"
38
+ ],
39
+ [
40
+ :else_clause,
41
+ [
42
+ :task_call_st,
43
+ "NoDiag"
44
+ ]
31
45
  ]
32
46
  ],
33
47
  [
34
- :task_call,
35
- "Diagnosis"
48
+ :task_call_st,
49
+ "Treatment"
36
50
  ]
37
- ],
38
- [
39
- :task_call,
40
- "Treatment"
41
51
  ]
42
52
  ]
43
53
  ]
@@ -7,6 +7,7 @@ SYNOPSIS
7
7
 
8
8
  OPTIONS
9
9
  --ast=[MODE] Prints the process abstract syntax tree (debug,ruby)
10
+ --no-sugar Apply syntactic sugar removal
10
11
  --help Show this help message
11
12
  --version Show version and exit
12
13
 
@@ -19,4 +20,8 @@ DESCRIPTION
19
20
  debugging, that is with colors and extra information. Use --ast=ruby to get a ruby
20
21
  array for automatic processing.
21
22
 
23
+ When --no-sugar is specified, syntactic sugar is first removed before making any other
24
+ transformation. For now, this rewrites all `if` statements as explicit `case` guarded
25
+ commands.
26
+
22
27
  SystemExit
@@ -0,0 +1 @@
1
+ gisele --no-sugar --ast=ruby tasks/simple.gis
@@ -0,0 +1,61 @@
1
+ [
2
+ :unit,
3
+ [
4
+ :task_def,
5
+ "Simple",
6
+ [
7
+ :task_signature,
8
+ [
9
+ :fluent,
10
+ "diagKnown",
11
+ [
12
+ :event_set,
13
+ "Diagnosis:start"
14
+ ],
15
+ [
16
+ :event_set,
17
+ "Treatment:end"
18
+ ],
19
+ nil
20
+ ]
21
+ ],
22
+ [
23
+ :task_refinement,
24
+ [
25
+ :seq_st,
26
+ [
27
+ :case_st,
28
+ [
29
+ :when_clause,
30
+ [
31
+ :bool_not,
32
+ [
33
+ :var_ref,
34
+ "diagKnown"
35
+ ]
36
+ ],
37
+ [
38
+ :task_call_st,
39
+ "Diagnosis"
40
+ ]
41
+ ],
42
+ [
43
+ :when_clause,
44
+ [
45
+ :var_ref,
46
+ "diagKnown"
47
+ ],
48
+ [
49
+ :task_call_st,
50
+ "NoDiag"
51
+ ]
52
+ ]
53
+ ],
54
+ [
55
+ :task_call_st,
56
+ "Treatment"
57
+ ]
58
+ ]
59
+ ]
60
+ ]
61
+ ]
@@ -1,15 +1,19 @@
1
- [:task, "Simple",
2
- [:signature,
3
- [:fluent, "diagKnown",
4
- [:event_set, "Diagnosis:start"],
5
- [:event_set, "Treatment:end"],
6
- nil ]
7
- ],
8
- [:refinement,
9
- [:seq,
10
- [:if,
11
- [:not, [:varref, "diagKnown"]],
12
- [:task_call, "Diagnosis"] ],
13
- [:task_call, "Treatment"]]
14
- ]
1
+ [:unit,
2
+ [:task_def, "Simple",
3
+ [:task_signature,
4
+ [:fluent, "diagKnown",
5
+ [:event_set, "Diagnosis:start"],
6
+ [:event_set, "Treatment:end"],
7
+ nil ]
8
+ ],
9
+ [:task_refinement,
10
+ [:seq_st,
11
+ [:if_st,
12
+ [:bool_not, [:var_ref, "diagKnown"]],
13
+ [:task_call_st, "Diagnosis"],
14
+ [:else_clause,
15
+ [:task_call_st, "NoDiag"] ]],
16
+ [:task_call_st, "Treatment"]]
17
+ ]
18
+ ]
15
19
  ]
@@ -3,6 +3,8 @@ task Simple
3
3
  refinement
4
4
  if not(diagKnown)
5
5
  Diagnosis
6
+ else
7
+ NoDiag
6
8
  end
7
9
  Treatment
8
10
  end
data/spec/spec_helper.rb CHANGED
@@ -11,7 +11,7 @@ ensure
11
11
  $stdout, $stderr = stdout, stderr
12
12
  end
13
13
 
14
- module Helpers
14
+ module SpecHelpers
15
15
 
16
16
  def fixtures_dir
17
17
  (Path.dir/:fixtures)
@@ -24,6 +24,6 @@ module Helpers
24
24
  end
25
25
 
26
26
  RSpec.configure do |c|
27
- c.extend Helpers
28
- c.include Helpers
27
+ c.extend SpecHelpers
28
+ c.include SpecHelpers
29
29
  end
@@ -1,14 +1,14 @@
1
1
  require 'spec_helper'
2
2
  describe "The examples" do
3
-
3
+
4
4
  (Path.backfind(".[examples]")/:examples).glob("**/*.gis").each do |file|
5
5
 
6
6
  describe file do
7
7
  it 'parses without any error' do
8
- Gisele::parse(file).should be_a(Array)
8
+ Gisele::ast(file).should be_a(Array)
9
9
  end
10
10
  end
11
11
 
12
12
  end
13
-
13
+
14
14
  end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+ module Gisele::Language::AST
3
+ describe Node do
4
+ include Helpers
5
+
6
+ describe 'rule_name' do
7
+ it 'returns the first array element' do
8
+ node([:hello]).rule_name.should eq(:hello)
9
+ end
10
+ end
11
+
12
+ describe 'children' do
13
+
14
+ it 'returns all but the rule name' do
15
+ node([:hello, "world", "!"]).children.should eq(["world", "!"])
16
+ end
17
+
18
+ it 'returns an empty array when no children' do
19
+ node([:hello]).children.should eq([])
20
+ end
21
+
22
+ end # children
23
+
24
+ describe 'copy' do
25
+
26
+ it 'collects block results ala `inject`' do
27
+ source = node([:unit, "world", "gisele"])
28
+ target = source.copy do |memo,child|
29
+ memo << child.upcase
30
+ end
31
+ target.should be_a(Unit)
32
+ target.should eq([:unit, "WORLD", "GISELE"])
33
+ end
34
+
35
+ it 'returns a real equal copy when no children' do
36
+ source = node([:unit])
37
+ target = source.copy do |memo,child| end
38
+ target.should eq(source)
39
+ target.object_id.should_not eq(source.object_id)
40
+ target.should be_a(Unit)
41
+ end
42
+
43
+ end
44
+
45
+ describe 'dup' do
46
+
47
+ it 'duplicates the underlying array' do
48
+ arr = [:unit, "etc."]
49
+ node(arr).dup.should eq(arr)
50
+ end
51
+
52
+ it 'ensures duplicated array is still a node' do
53
+ arr = [:unit, "etc."]
54
+ node(arr).dup.should be_a(Unit)
55
+ node(arr).dup.should be_a(Node)
56
+ end
57
+
58
+ end # dup
59
+
60
+ end
61
+ end