aster 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|