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 +4 -4
- data/README.md +19 -3
- data/TODO +9 -1
- data/aster.gemspec +1 -0
- data/lib/aster.rb +1 -0
- data/lib/aster/command.rb +17 -10
- data/lib/aster/environment.rb +64 -40
- data/lib/aster/macro.rb +12 -0
- data/lib/aster/parser.rb +9 -2
- data/lib/aster/sexp.treetop +0 -5
- data/lib/aster/version.rb +1 -1
- data/test/test_environment.rb +39 -2
- data/test/test_parser.rb +13 -0
- metadata +16 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0c85417587339f5f431df3347c2045046b742aae
|
4
|
+
data.tar.gz: 72836e9ed31cd3f4ba159509bebcbbfe28bca42c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
-
|
48
|
+
### Install
|
47
49
|
|
48
50
|
gem install aster
|
49
51
|
|
50
|
-
|
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
data/aster.gemspec
CHANGED
data/lib/aster.rb
CHANGED
data/lib/aster/command.rb
CHANGED
@@ -1,24 +1,31 @@
|
|
1
1
|
module Aster
|
2
2
|
class Command
|
3
|
-
attr_accessor :text, :
|
3
|
+
attr_accessor :text, :sub_commands, :sub_text
|
4
4
|
|
5
|
-
def initialize(commands,
|
6
|
-
@commands = commands
|
7
|
-
@
|
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
|
-
|
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
|
data/lib/aster/environment.rb
CHANGED
@@ -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
|
-
|
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
|
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.
|
65
|
+
command.sub_commands
|
54
66
|
)
|
55
67
|
when :if
|
56
|
-
cond_value =
|
68
|
+
cond_value = eval_command Command.new(command.rest)
|
57
69
|
if is_true?(cond_value)
|
58
|
-
eval_tree command.
|
70
|
+
eval_tree command.sub_commands
|
59
71
|
end
|
60
72
|
when :not
|
61
|
-
cond_value =
|
73
|
+
cond_value = eval_arguments([command.arguments.first]).first
|
62
74
|
is_true?(cond_value) ? "no" : "yes"
|
63
75
|
else
|
64
|
-
|
65
|
-
|
66
|
-
eval_function(
|
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
|
-
|
98
|
+
arg
|
69
99
|
end
|
70
100
|
end
|
71
101
|
end
|
72
102
|
|
73
103
|
def is_true?(val)
|
74
|
-
val &&
|
104
|
+
val && val.strip == "yes"
|
75
105
|
end
|
76
106
|
|
77
107
|
def eval_tree(tree)
|
78
|
-
tree.
|
79
|
-
|
80
|
-
end
|
108
|
+
tree.map do |command|
|
109
|
+
res = eval_command command
|
110
|
+
end.last
|
81
111
|
end
|
82
112
|
|
83
|
-
def
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
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
|
-
|
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
|
data/lib/aster/macro.rb
ADDED
data/lib/aster/parser.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/aster/sexp.treetop
CHANGED
@@ -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 {
|
data/lib/aster/version.rb
CHANGED
data/test/test_environment.rb
CHANGED
@@ -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
|
-
|
8
|
-
|
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
|
data/test/test_parser.rb
CHANGED
@@ -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.
|
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
|