aster 0.0.1 → 0.0.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 58243f4638f7370eaedd71419622f967f24bd60e
4
- data.tar.gz: 8426cc93373842fb7cf66d2fcc3c389a47cdecf1
3
+ metadata.gz: 0c85417587339f5f431df3347c2045046b742aae
4
+ data.tar.gz: 72836e9ed31cd3f4ba159509bebcbbfe28bca42c
5
5
  SHA512:
6
- metadata.gz: 1adc2b41461422e04081c6fa8c4d9f2c460b8661691ee0aff87bacf5fc7d9b611fa031a7e1115b680221e767f071ec0c61ca953d44761e2062191fbb863a7ae4
7
- data.tar.gz: 1cdcbe16dff0aaf31ec201df89181461416f94d3c1044d890de17ad664b60c8a06fcf7f8b6622266cc051f950fe647b2d3172770a2d3e3e7b3439b194bcd65ef
6
+ metadata.gz: 54058d24e135d2efee5e8abfc2755b32067f84a4f4210029cdfa688460d478b43ab4ca6f83f2a3904b65a7ea93eb4e84bed1d2e98367e3e0fcac974573122557
7
+ data.tar.gz: b8d77eb5a75520e918749ebb2e875e3488e25e055c017749a853db83d662caa3da0a975352e36880a45219e18f6b02106786e0aee8d1dbb75ea0ea78181758b5
data/README.md CHANGED
@@ -2,9 +2,10 @@
2
2
 
3
3
  Aster is a programming language that's designed to make configuration management more fun.
4
4
 
5
- ## Example
5
+ ### Example
6
6
 
7
7
  server web
8
+
8
9
  default-instance-vars
9
10
  var username root
10
11
  var ssh-port 22
@@ -17,6 +18,7 @@ Aster is a programming language that's designed to make configuration management
17
18
  config-set username admin
18
19
  config-set ssh-port 2222
19
20
  upload sample.conf /etc/conf
21
+ exec set-hostname $instance.hostname
20
22
 
21
23
  add-remote-file-runner .rb
22
24
  exec `which ruby`
@@ -43,10 +45,24 @@ Aster is a programming language that's designed to make configuration management
43
45
  create-server-instance web
44
46
  configure-instance {{instance.id}}
45
47
 
46
- ## Install
48
+ ### Install
47
49
 
48
50
  gem install aster
49
51
 
50
- ## Usage
52
+ ### Usage
53
+
54
+ #### Adding ruby-side macro
55
+
56
+ class Server
57
+ end
58
+
59
+ e = Aster::Environment.new
60
+
61
+ # Make a special form of "server" that
62
+ e.define_macro "server" do |arguments, body|
63
+ body.parse_tree
64
+ end
65
+
66
+ ### Notes
51
67
 
52
68
  Aster is not a configuration management application. Right now it is an experimental language that supports other languages embedded within `.aster` files.
data/TODO CHANGED
@@ -1,4 +1,12 @@
1
1
  # TODO
2
2
 
3
- * reserve gem name
3
+
4
+
5
+ # Done
6
+
7
+ * implement sub-language text gathering
8
+ * implement ruby-side macros
9
+ * implement equal
10
+ * implement not
4
11
  * eval sub-commands like "equal {add 1 1} 2"
12
+ * reserve gem name
@@ -24,4 +24,5 @@ Gem::Specification.new do |spec|
24
24
  spec.add_development_dependency "bundler", "~> 1.6"
25
25
  spec.add_development_dependency "rake"
26
26
  spec.add_development_dependency "pry"
27
+ spec.add_development_dependency "ZenTest"
27
28
  end
@@ -12,4 +12,5 @@ require_relative './aster/command'
12
12
  require_relative './aster/environment'
13
13
  require_relative './aster/function'
14
14
  require_relative './aster/parser'
15
+ require_relative './aster/macro'
15
16
 
@@ -1,24 +1,31 @@
1
1
  module Aster
2
2
  class Command
3
- attr_accessor :text, :sublines
3
+ attr_accessor :text, :sub_commands, :sub_text
4
4
 
5
- def initialize(commands, sublines = [])
6
- @commands = commands
7
- @sublines = sublines
8
- end
9
-
10
- def rest
11
- @text.split(' ', 2)[1]
5
+ def initialize(commands, subcommands = [])
6
+ @commands = make_commands commands
7
+ @sub_commands = sub_commands
12
8
  end
13
9
 
14
10
  def arguments
15
- _, *args = @commands
16
- args
11
+ @commands[1..-1]
17
12
  end
18
13
 
19
14
  def function_name
20
15
  @function_name ||= @commands.first.to_sym
21
16
  end
22
17
 
18
+ private
19
+
20
+ def make_commands(cmds)
21
+ cmds.map do |cmd|
22
+ if cmd.is_a?(Array)
23
+ Command.new(cmd)
24
+ else
25
+ cmd
26
+ end
27
+ end
28
+ end
29
+
23
30
  end
24
31
  end
@@ -7,17 +7,9 @@ module Aster
7
7
  def initialize(parent = nil)
8
8
  @parent = parent
9
9
  @env = {}
10
- @stdout = ""
11
- @stderr = ""
10
+ @stdout, @stderr = "", ""
12
11
 
13
- if parent.nil?
14
- define_function :echo, [:_list_] do |arguments|
15
- @stdout << arguments.join(' ')
16
- end
17
- define_function :equal, [:a, :b] do |(a, b)|
18
- a.to_s == b.to_s ? "yes" : "no"
19
- end
20
- end
12
+ define_base_environment if parent.nil?
21
13
  end
22
14
 
23
15
  def child
@@ -38,59 +30,97 @@ module Aster
38
30
  end
39
31
 
40
32
  def define_function(name, args, commands = nil, &block)
41
- @env[name.to_sym] = Function.new(args, commands, &block)
33
+ self[name] = Function.new(args, commands, &block)
34
+ end
35
+
36
+ def define_macro(name, &block)
37
+ self[name] = Macro.new self, block
42
38
  end
43
39
 
44
40
  private
45
41
 
46
- def eval_line(command)
42
+ def define_base_environment
43
+ define_function :echo, [:_list_] do |arguments|
44
+ @stdout << arguments.join(' ')
45
+ end
46
+
47
+ define_function :equal, [:a, :b] do |(a, b)|
48
+ a.to_s == b.to_s ? "yes" : "no"
49
+ end
50
+
51
+ define_function :add, [:_list_] do |arguments|
52
+ arguments.inject(0){|r, s| s.to_i + r}.to_s
53
+ end
54
+
55
+ end
56
+
57
+
58
+ def eval_command(command)
47
59
  case command.function_name
48
60
  when :function
49
61
  fun, *args = command.arguments
50
62
  self.define_function(
51
63
  fun,
52
64
  args,
53
- command.sublines
65
+ command.sub_commands
54
66
  )
55
67
  when :if
56
- cond_value = eval_line Command.new(command.rest)
68
+ cond_value = eval_command Command.new(command.rest)
57
69
  if is_true?(cond_value)
58
- eval_tree command.sublines
70
+ eval_tree command.sub_commands
59
71
  end
60
72
  when :not
61
- cond_value = eval_line Command.new(command.rest)
73
+ cond_value = eval_arguments([command.arguments.first]).first
62
74
  is_true?(cond_value) ? "no" : "yes"
63
75
  else
64
- function = self[command.function_name]
65
- if function
66
- eval_function(function, command.arguments, self.child)
76
+ case function_or_macro = self[command.function_name]
77
+ when Function
78
+ eval_function(
79
+ function_or_macro,
80
+ eval_arguments(command.arguments),
81
+ self.child
82
+ )
83
+ when Macro
84
+ eval_macro(function_or_macro, command)
85
+ else
86
+ # ? binding.pry
87
+ end
88
+ end
89
+ end
90
+
91
+ def eval_arguments(arguments)
92
+ arguments.map do |arg|
93
+ if arg.is_a?(Command)
94
+ eval_command(arg)
95
+ elsif arg.is_a?(Variable)
96
+ self[arg.name]
67
97
  else
68
- #binding.pry
98
+ arg
69
99
  end
70
100
  end
71
101
  end
72
102
 
73
103
  def is_true?(val)
74
- val && value.strip == "yes"
104
+ val && val.strip == "yes"
75
105
  end
76
106
 
77
107
  def eval_tree(tree)
78
- tree.each do |command|
79
- eval_line command
80
- end
108
+ tree.map do |command|
109
+ res = eval_command command
110
+ end.last
81
111
  end
82
112
 
83
- def eval_function(function, arguments, env)
84
- # need to eval args
85
- arguments = arguments.map do |arg|
86
- if arg.is_a?(Variable)
87
- env[arg.name]
88
- else
89
- arg
90
- end
113
+ def eval_macro(macro, command)
114
+ command_or_commands = macro.function(command)
115
+ if command_or_commands.is_a?(Array)
116
+ eval_tree command_or_commands
117
+ else
118
+ eval_command command_or_commands
91
119
  end
120
+ end
92
121
 
93
- # bind arguments
122
+ def eval_function(function, arguments, env)
123
+ # bind arguments to new env
94
124
  function.arguments.each_with_index do |a, i|
95
125
  env[a] = arguments[i]
96
126
  end
@@ -101,13 +131,7 @@ module Aster
101
131
  function.block.call arguments
102
132
  else
103
133
  raise
104
- end
105
-
106
- end
107
-
108
-
109
- def eval_custom(m, args)
110
-
134
+ end
111
135
  end
112
136
 
113
137
  end
@@ -0,0 +1,12 @@
1
+ class Macro
2
+
3
+ def initialize(env, block)
4
+ @env = env
5
+ @block = block
6
+ end
7
+
8
+ def function(command)
9
+ @block.call command
10
+ end
11
+
12
+ end
@@ -1,4 +1,3 @@
1
-
2
1
  require 'treetop'
3
2
 
4
3
  module Aster
@@ -59,7 +58,15 @@ module Aster
59
58
  break
60
59
  end
61
60
  end
62
- command.sublines = parse_lines sublines
61
+
62
+ begin
63
+ command.sub_commands = parse_lines sublines
64
+ rescue
65
+ command.sub_commands = :GARBAGE
66
+ end
67
+ command.sub_text = sublines.map do |subline|
68
+ subline.gsub(/^[ ]{#{next_indent*2}}/, '')
69
+ end.join("\n")
63
70
  end
64
71
  data << command
65
72
  end
@@ -1,6 +1,3 @@
1
-
2
-
3
-
4
1
  grammar Sexp
5
2
 
6
3
  rule body
@@ -13,7 +10,6 @@ grammar Sexp
13
10
  end
14
11
  }
15
12
  end
16
-
17
13
 
18
14
  rule expression
19
15
  space? '{' body '}' space? {
@@ -25,7 +21,6 @@ grammar Sexp
25
21
  end
26
22
  }
27
23
  end
28
-
29
24
 
30
25
  rule variable
31
26
  '$' identifier {
@@ -1,3 +1,3 @@
1
1
  module Aster
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -2,10 +2,32 @@ require_relative './helper'
2
2
 
3
3
  class TestEnvironment < Test::Unit::TestCase
4
4
 
5
+ def eval(text)
6
+ Aster::Environment.new.eval(text)
7
+ end
8
+
5
9
  def test_not
6
10
  e = Aster::Environment.new
7
- #assert_equal "no", e.eval("not yes")
8
- #assert_equal "yes", e.eval("not no")
11
+ assert_equal "no", e.eval("not yes")
12
+ assert_equal "yes", e.eval("not no")
13
+ end
14
+
15
+ def test_sub_not
16
+ e = Aster::Environment.new
17
+ assert_equal "no", e.eval("not {not no}")
18
+ assert_equal "yes", e.eval("not {not {not no}}")
19
+ end
20
+
21
+ def test_equal
22
+ e = Aster::Environment.new
23
+ assert_equal "yes", e.eval("equal 1 1")
24
+ assert_equal "yes", e.eval("equal {not no} yes")
25
+ end
26
+
27
+ def test_add
28
+ assert_equal "12", eval("add 6 6")
29
+ assert_equal "6", eval("add 1 2 3")
30
+ assert_equal "12", eval("add 1 2 3 {add 3 3}")
9
31
  end
10
32
 
11
33
  def test_function
@@ -15,4 +37,19 @@ class TestEnvironment < Test::Unit::TestCase
15
37
  assert_equal("one and two", e.stdout)
16
38
  end
17
39
 
40
+ def test_macro
41
+ e = Aster::Environment.new
42
+ e.define_macro :double do |c|
43
+ assert_kind_of Aster::Command, c
44
+ tree = Aster::Parser.new.parse("add #{c.arguments.first} #{c.arguments.first}")
45
+ tree.first
46
+ end
47
+ assert_equal "32", e.eval("double 16")
48
+ end
49
+
50
+ def test_env
51
+
52
+
53
+ end
54
+
18
55
  end
@@ -55,4 +55,17 @@ function test2 asdf
55
55
  tree = parser.parse file
56
56
  end
57
57
 
58
+ def test_ruby_script
59
+ tree = parse %Q{
60
+ ruby
61
+ require 'rubygems'
62
+ a = ArchiveRecord::Base;
63
+ a.define "s" do |asdf|
64
+ asdf.asdf << #end
65
+ end
66
+ }
67
+ text = "require 'rubygems'\na = ArchiveRecord::Base;\na.define \"s\" do |asdf|\n asdf.asdf << #end\nend\n "
68
+ assert_equal text, tree.first.sub_text
69
+ end
70
+
58
71
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aster
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Murphy
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - '>='
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: ZenTest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  description:
70
84
  email:
71
85
  - sam.murphy@gmail.com
@@ -84,6 +98,7 @@ files:
84
98
  - lib/aster/command.rb
85
99
  - lib/aster/environment.rb
86
100
  - lib/aster/function.rb
101
+ - lib/aster/macro.rb
87
102
  - lib/aster/parser.rb
88
103
  - lib/aster/sexp.treetop
89
104
  - lib/aster/variable.rb