yadriggy 1.0.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.
@@ -0,0 +1,86 @@
1
+ # Copyright (C) 2017- Shigeru Chiba. All rights reserved.
2
+
3
+ require 'yadriggy/c/c'
4
+ require 'yadriggy/c/config'
5
+
6
+ module Yadriggy
7
+ module C
8
+ class Program
9
+ include Yadriggy::C::CType
10
+
11
+ # Compiles this class and makes a module including the
12
+ # compiled methods.
13
+ #
14
+ # @param [String] module_name the name of the module where
15
+ # methods are attached. If it is not nil, a Ruby script
16
+ # is generated. When it is executed later, the methods are
17
+ # attached to the module with `module_name`.
18
+ # The name of the generated Ruby script is `#{lib_name}.rb`.
19
+ # @param [String] lib_name the name of the generated library.
20
+ # @param [String] dir the directory name where generated files
21
+ # are stored.
22
+ # @return [Module] the module where methods are attached.
23
+ # Note that the name of this module is nil.
24
+ # It is not `method_name`.
25
+ def self.compile(module_name=nil, lib_name=nil, dir: Config::WorkDir)
26
+ obj = self.new
27
+ Yadriggy::C.compile(obj, lib_name, dir, module_name)
28
+ end
29
+
30
+ # Prints arguments. This method is available from C code.
31
+ # It takes arguments as `printf` in C. For example,
32
+ # `printf('value %d', 7)` is a valid call.
33
+ # Note that the argument types are not checked.
34
+ def printf(s) ! Void
35
+ typedecl s: String, foreign: Void
36
+ puts s
37
+ end
38
+
39
+ # Gets the current time in micro sec.
40
+ # @return [Time] the current time. In C, an integer is returned.
41
+ def current_time() ! Int
42
+ typedecl native: "struct timespec time;\n\
43
+ clock_gettime(CLOCK_MONOTONIC, &time);\n\
44
+ return time.tv_sec * 1000000 + time.tv_nsec / 1000;"
45
+ Time.now * 1000000
46
+ end
47
+
48
+ # Square root function with single precision.
49
+ def sqrtf(f)
50
+ typedecl f: Float, foreign: Float
51
+ Math.sqrt(f)
52
+ end
53
+
54
+ # Square root function.
55
+ def sqrt(f)
56
+ typedecl f: Float, foreign: Float
57
+ Math.sqrt(f)
58
+ end
59
+
60
+ # Exponential function with single precision.
61
+ def expf(f)
62
+ typedecl f: Float, foreign: Float
63
+ Math.exp(f)
64
+ end
65
+
66
+ # Exponential function.
67
+ def exp(f)
68
+ typedecl f: Float, foreign: Float
69
+ Math.exp(f)
70
+ end
71
+
72
+ # Logarithm function with single precision.
73
+ def logf(f)
74
+ typedecl f: Float, foreign: Float
75
+ Math.log(f)
76
+ end
77
+
78
+ # Logarithm function.
79
+ def log(f)
80
+ typedecl f: Float, foreign: Float
81
+ Math.log(f)
82
+ end
83
+
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,10 @@
1
+ # Copyright (C) 2017- Shigeru Chiba. All rights reserved.
2
+
3
+ require 'yadriggy'
4
+ require 'yadriggy/c1/c1'
5
+
6
+ module Yadriggy
7
+ # Simple C language
8
+ module C1
9
+ end
10
+ end
@@ -0,0 +1,216 @@
1
+ # Copyright (C) 2017- Shigeru Chiba. All rights reserved.
2
+
3
+ require 'yadriggy/ast'
4
+
5
+ module Yadriggy
6
+
7
+ # Exception thrown by a checker.
8
+ class CheckError < RuntimeError
9
+ end
10
+
11
+ # AST checker.
12
+ # It visits the AST nodes and does various checks like type checking.
13
+ class Checker
14
+ include Yadriggy
15
+
16
+ # Defines the rule for a node type.
17
+ #
18
+ # @param [Class] node_type the type of the AST node.
19
+ # @yield The block is executed for the node with `node_type`.
20
+ # @return [void]
21
+ def self.rule(node_type, &proc)
22
+ init_class if @rules.nil?
23
+ @rules[node_type] = proc
24
+ @rule_declarators[node_type] = self
25
+ end
26
+
27
+ # @private
28
+ # Initializes this class if necessary.
29
+ def self.check_init_class
30
+ init_class if @rules.nil?
31
+ end
32
+
33
+ # @private
34
+ # @return [Array<Hash>] all the rules defined so far.
35
+ def self.all_rules
36
+ [@rules, @rule_declarators]
37
+ end
38
+
39
+ private_class_method def self.init_class
40
+ @rules = {}
41
+ @rule_declarators = {}
42
+ unless self.superclass == Object
43
+ all = self.superclass.all_rules
44
+ unless all[0].nil?
45
+ @rules = all[0].clone
46
+ @rule_declarators = all[1].clone
47
+ end
48
+ end
49
+ end
50
+
51
+ # @private
52
+ # internal-use only. Don't call this.
53
+ # @return [Pair<Proc,Class>] a rule and the class declaring it, or nil.
54
+ #
55
+ def self.find_rule_entry(ast)
56
+ find_rule_entry2(ast.class, ast.usertype)
57
+ end
58
+
59
+ private_class_method def self.find_rule_entry2(ast_class, utype)
60
+ unless utype.nil?
61
+ rule = @rules[utype]
62
+ return [rule, @rule_declarators[utype]] unless rule.nil?
63
+ end
64
+
65
+ rule = @rules[ast_class]
66
+ if rule.nil?
67
+ if ast_class.superclass.nil?
68
+ nil
69
+ else
70
+ find_rule_entry2(ast_class.superclass, utype)
71
+ end
72
+ else
73
+ [rule, @rule_declarators[ast_class]]
74
+ end
75
+ end
76
+
77
+ # Initializes the object.
78
+ def initialize
79
+ self.class.check_init_class
80
+ @error = nil
81
+ @check_list = []
82
+ @current_ast = nil
83
+ @current_env = nil
84
+ @rule_declarator = nil
85
+ end
86
+
87
+ # @return [String] an error message when the last invocation of check()
88
+ # returns nil.
89
+ def error
90
+ @error || ''
91
+ end
92
+
93
+ # Applies rules to the given AST.
94
+ # It returns the result of the rule-application or throws
95
+ # a CheckError.
96
+ # This is the entry point of the checker. It may also
97
+ # check the other ASTs invoked in the given AST.
98
+ #
99
+ # @param [ASTree|ASTnode] an_ast the AST.
100
+ # @return [Object]
101
+ def check_all(an_ast)
102
+ return nil if an_ast.nil?
103
+ an_ast = an_ast.tree if an_ast.is_a?(ASTree)
104
+ t = check(an_ast, make_base_env(an_ast.get_context_class))
105
+ until (checked = @check_list.pop).nil?
106
+ @current_ast = checked[0]
107
+ @current_env = checked[1]
108
+ checked[2].call
109
+ end
110
+ t
111
+ end
112
+
113
+ # Makes a new base environment with the given context class.
114
+ # @param [Module] klass the context class.
115
+ def make_base_env(klass)
116
+ klass
117
+ end
118
+
119
+ # Applies rules to the given AST.
120
+ #
121
+ # It assumes that ast is processed by Syntax and it has usertype method.
122
+ # An exception is thrown when the checking fails.
123
+ # ast may be nil.
124
+ #
125
+ # The environment given to this method can be accessed in the rules
126
+ # through ast_env(). It is optional and can be any object.
127
+ # The initial one is made by make_base_env().
128
+ #
129
+ # @return [Object]
130
+ def check(an_ast, ast_env=nil)
131
+ if an_ast.nil?
132
+ nil
133
+ else
134
+ rule = self.class.find_rule_entry(an_ast)
135
+ apply_typing_rule(rule, an_ast, ast_env)
136
+ end
137
+ end
138
+
139
+ # @private
140
+ # internal use only
141
+ def apply_typing_rule(rule, an_ast, ast_tenv)
142
+ if rule.nil?
143
+ error_found!(an_ast, "no typing rule for #{an_ast.class}")
144
+ else
145
+ old_ast = @current_ast
146
+ old_tenv = @current_env
147
+ old_declarator = @rule_declarator
148
+ @current_ast = an_ast
149
+ @current_env = ast_tenv unless ast_tenv.nil?
150
+ @rule_declarator = rule[1]
151
+ t = instance_exec(&rule[0])
152
+ @rule_declarator = old_declarator
153
+ @current_env = old_tenv
154
+ @current_ast = old_ast
155
+ return t
156
+ end
157
+ end
158
+
159
+ # Applies the rule supplied by the superclass.
160
+ # @param [ASTnode] an_ast an AST.
161
+ # @param [Object] envi an environment object.
162
+ # @return [Type] the type of the given AST.
163
+ def proceed(an_ast, envi=nil)
164
+ rule = if @rule_declarator&.superclass == Object
165
+ nil
166
+ else
167
+ @rule_declarator&.superclass.find_rule_entry(an_ast)
168
+ end
169
+ if rule.nil?
170
+ error_found!(an_ast, 'no more rule. we cannot proceed')
171
+ else
172
+ apply_typing_rule(rule, an_ast, envi)
173
+ end
174
+ end
175
+
176
+ # @return [ASTnode] the current abstract syntax tree.
177
+ def ast
178
+ @current_ast
179
+ end
180
+
181
+ # @return [Object] the current environment.
182
+ def ast_env
183
+ @current_env
184
+ end
185
+
186
+ # Later invokes the block, which performs checking.
187
+ # The method immediately returns.
188
+ # This is used for avoiding infinite regression during the checking.
189
+ # @yield The block is later executed for checking.
190
+ # @return [void]
191
+ def check_later(&proc)
192
+ cur_ast = @current_ast
193
+ cur_env = @current_env
194
+ @check_list << [cur_ast, cur_env, proc]
195
+ end
196
+
197
+ # @private
198
+ def error_found!(an_ast, msg='')
199
+ loc = if an_ast.is_a?(ASTnode)
200
+ an_ast.source_location_string
201
+ else
202
+ ''
203
+ end
204
+ @error = "#{loc} DSL #{error_group} error. #{msg}"
205
+ binding.pry if Yadriggy.debug > 1
206
+ raise CheckError.new(@error)
207
+ end
208
+
209
+ # @private
210
+ def error_group
211
+ ''
212
+ end
213
+
214
+ init_class
215
+ end
216
+ end
@@ -0,0 +1,200 @@
1
+ # Copyright (C) 2017- Shigeru Chiba. All rights reserved.
2
+
3
+ module Yadriggy
4
+
5
+ # abstract evaluator (using visitor pattern)
6
+ #
7
+ class Eval
8
+ def evaluate(expr)
9
+ if expr.nil?
10
+ nil_value(nil)
11
+ else
12
+ expr.accept(self)
13
+ end
14
+ self
15
+ end
16
+
17
+ # A root.
18
+ #
19
+ def astree(expr)
20
+ evaluate(expr.tree)
21
+ end
22
+
23
+ def nil_value(expr)
24
+ raise NotImplementedError.new('nil_value')
25
+ end
26
+
27
+ def name(expr)
28
+ raise NotImplementedError.new('name')
29
+ end
30
+
31
+ def identifier_or_call(expr)
32
+ name(expr)
33
+ end
34
+
35
+ def identifier(expr)
36
+ identifier_or_call(expr)
37
+ end
38
+
39
+ def reserved(expr)
40
+ name(expr)
41
+ end
42
+
43
+ def const(expr)
44
+ name(expr)
45
+ end
46
+
47
+ def label(expr)
48
+ name(expr)
49
+ end
50
+
51
+ def symbol(expr)
52
+ raise NotImplementedError.new('symbol')
53
+ end
54
+
55
+ def global_variable(expr)
56
+ name(expr)
57
+ end
58
+
59
+ def instance_variable(expr)
60
+ name(expr)
61
+ end
62
+
63
+ def variable_call(expr)
64
+ identifier_or_call(expr)
65
+ end
66
+
67
+ def super_method(expr)
68
+ raise NotImplementedError.new('super_method')
69
+ end
70
+
71
+ def number(expr)
72
+ raise NotImplementedError.new('number')
73
+ end
74
+
75
+ # expressions, or progn in Lisp.
76
+ #
77
+ def exprs(expr)
78
+ raise NotImplementedError.new('exprs')
79
+ end
80
+
81
+ def paren(expr)
82
+ raise NotImplementedError.new('paren')
83
+ end
84
+
85
+ def array(expr)
86
+ raise NotImplementedError.new('array')
87
+ end
88
+
89
+ def string_interpolation(expr)
90
+ raise NotImplementedError.new('string_interpolation')
91
+ end
92
+
93
+ def string_literal(expr)
94
+ raise NotImplementedError.new('string_literal')
95
+ end
96
+
97
+ def const_path_ref(expr)
98
+ raise NotImplementedError.new('const_path_ref')
99
+ end
100
+
101
+ def const_path_field(expr)
102
+ const_path_ref(expr)
103
+ end
104
+
105
+ def unary(expr)
106
+ raise NotImplementedError.new('unary')
107
+ end
108
+
109
+ def binary(expr)
110
+ raise NotImplementedError.new('binary')
111
+ end
112
+
113
+ def dots(expr)
114
+ binary(expr)
115
+ end
116
+
117
+ def assign(expr)
118
+ binary(expr)
119
+ end
120
+
121
+ def array_ref(expr)
122
+ raise NotImplementedError.new('array')
123
+ end
124
+
125
+ def array_ref_field(expr)
126
+ array_ref(expr)
127
+ end
128
+
129
+ def hash(expr)
130
+ raise NotImplementedError.new('hash')
131
+ end
132
+
133
+ def call(expr)
134
+ raise NotImplementedError.new('call')
135
+ end
136
+
137
+ def command(expr)
138
+ call(expr)
139
+ end
140
+
141
+ def conditional(expr)
142
+ raise NotImplementedError.new('conditional')
143
+ end
144
+
145
+ def loop(expr)
146
+ raise NotImplementedError.new('loop')
147
+ end
148
+
149
+ def for_loop(expr)
150
+ raise NotImplementedError.new('for_loop')
151
+ end
152
+
153
+ def break_out(expr)
154
+ raise NotImplementedError.new('break_out')
155
+ end
156
+
157
+ def return_values(expr)
158
+ raise NotImplementedError.new('return_values')
159
+ end
160
+
161
+ def block(expr)
162
+ raise NotImplementedError.new('block')
163
+ end
164
+
165
+ def lambda_expr(expr)
166
+ block(expr)
167
+ end
168
+
169
+ def being_end(expr)
170
+ raise NotImplementedError.new('begin_end')
171
+ end
172
+
173
+ # def
174
+ #
175
+ def define(expr)
176
+ raise NotImplementedError.new('define')
177
+ end
178
+
179
+ def rescue_end(expr)
180
+ raise NotImplementedError.new('rescue_end')
181
+ end
182
+
183
+ def module_def(expr)
184
+ raise NotImplementedError.new('module_def')
185
+ end
186
+
187
+ def class_def(expr)
188
+ raise NotImplementedError.new('class_def')
189
+ end
190
+
191
+ def singular_class_def(expr)
192
+ raise NotImplementedError.new('singular_class_def')
193
+ end
194
+
195
+ def program(expr)
196
+ raise NotImplementedError.new('program')
197
+ end
198
+ end
199
+
200
+ end