class RubyGenerator(CodeGenerator): '''Ruby code generator''' indent = 2 use_spaces = True middlewares = [] def ruby_dict(self, node, indent): short_syntax = True result = [] for pair in node.pairs: if short_syntax and pair.key.type == 'string' and re.match(SHORT_SYNTAX, pair.key.value): result.append('%s: %s' % (pair.key.value, self._generate_node(pair.value))) else: short_syntax = False result.append('%s => %s' % (self._generate_node(pair.key), self._generate_node(pair.value))) return ', '.join(result) call_args = ("(%<args:join ', '>)", '') function_params = ("(%<params:join ', '>)", '') templates = dict( module = ''' %<dependencies:lines> %<custom_exceptions:lines> %<definitions:lines> %<main:lines>''', function_definition = ''' def %<name>%<.params> %<block:line_join> end''', function_definition_params = function_params, method_definition = ''' def %<name>%<.params> %<block:line_join> end''', method_definition_params = function_params, constructor = ''' def initialize%<.params> %<block:line_join> end''', constructor_params = function_params, class_definition = ''' class %<name>%<.base> %<.constructor> %<methods:lines> end''', class_definition_constructor = ('%<constructor>', ''), class_definition_base = ('< %<base>', ''), local = '%<name>', typename = '%<name>', int = '%<value>', float = '%<value>', string = '%<#safe_single_except_nl>', boolean = '%<value>', null = 'nil', dependency = "require '%<name>'", list = "[%<elements:join ', '>]", dictionary = '{%<#ruby_dict>}', attr = '%<object>.%<attr>', assignment = '%<target> = %<value>', binary_op = '%<#binary_left> %<#op> %<#binary_right>', unary_op = '%<#op>%<value>', comparison = '%<#right>', static_call = "%<receiver>.%<message>%<.args>", static_call_args = call_args, call = switch( lambda c: c.function.type == 'local' and c.function.name in ['puts', 'p'] or len(c.args) == 0, true = "%<function>%<args:join_lws ', '>", _otherwise = "%<function>(%<args:join ', '>)" ), call_args = call_args, method_call_args = call_args, method_call = "%<receiver>.%<message>%<.args>", this_method_call = "%<message:camel_case 'title'>%<.args>", this_method_call_args=call_args, this = 'self', instance_variable = '@%<name>', throw_statement = 'throw %<exception>.new(%<value>)', new_instance = "%<class_name>.new%<args:join ', '>", new_instance_args = call_args, standard_iterable_call = "%<sequences.sequence>.select { |%<iterators>| %<test:first> }.map { |%<iterators>| %<block:first> }", if_statement = ''' if %<test> %<block:line_join> %<.otherwise>''', if_statement_otherwise = ('%<otherwise>', 'end'), elseif_statement = ''' elsif %<test> %<block:line_join> %<.otherwise>''', elseif_statement_otherwise = ('%<otherwise>', 'end'), else_statement = ''' else %<block:line_join> end''', not_null_check = '!%<value>.nil?', while_statement = ''' while %<test> %<block:line_join> end''', try_statement = ''' begin %<block:line_join> %<handlers:line_join>end ''', exception_handler = ''' rescue %<.is_builtin> => %<instance> %<block:line_join>''', exception_handler_is_builtin = ('StandardError', '%<exception>'), for_statement = ''' %<sequences> do |%<iterators>| %<block:line_join> end''', for_range_statement = ''' (%<.first>...%<end>)%<.step>.each do |%<index>| %<block:line_join> end''', for_range_statement_first = ('%<start>', '0'), for_range_statement_step = ('.step(%<step>)', ''), for_each_with_index_statement = ''' %<#index_sequence> do |%<#index_iterator>| %<block:line_join> end''', for_sequence = '%<sequence>.each', for_sequence_zip = "%<sequences:first>.zip(%<sequences:join_rest ', '>).each", for_sequence_with_index = '%<sequence>.each_with_index', for_sequence_with_items = '%<sequence>.each', for_iterator = '%<iterator>', for_iterator_zip = "%<iterators:join ', '>", for_iterator_with_index = '%<iterator>, %<index>', for_iterator_with_items = '%<key>, %<value>', explicit_return = 'return %<value>', implicit_return = '%<value>', custom_exception = ''' class %<name> < %<.base> end''', custom_exception_base = ('%<base>', 'StandardError'), _rb_slice = '%<sequence>[%<from_>...%<to>]', _rb_slice_from = '%<sequence>[%<from_>..-1]', _rb_slice_to = '%<sequence>[0..%<to>]', anonymous_function = switch( lambda a: len(a.block) == 1, true = "->%<params:join_lws ', '> { %<block:join ''> }", _otherwise = ''' ->%<params:join_lws ', '> do %<block:line_join> end''' ), _rb_method_call_block = "%<receiver>.%<message>%<.args> %<block>", _rb_method_call_block_args = call_args, _rb_block = switch(lambda b: len(b.block) == 1, true = "{ |%<params:join ', '>| %<block:first> }", _otherwise = ''' do |%<params:join ', '>| %<block:line_join> end'''), _rb_regex_interpolation = "/#{%<value>}/", index = '%<sequence>[%<index>]', interpolation = "\"%<args:join ''>\"", interpolation_literal = '%<value>', interpolation_placeholder = '#{%<value>}', aug_assignment = '%<target> %<op>= %<value>', tuple = "[%<elements:join ', '>]", array = "[%<elements:join ', '>]", set = "Set.new([%<elements:join ', '>])", block = '%<block:line_join>', regex = "/%<value>/", ) def op(self, node, depth): return OPS.get(node.op, node.op) def right(self, node, depth): '''when compared with argv length, decrement''' if node.left.type != 'binary_op' or node.left.op != '+' or node.left.right.type != 'int' or node.right.type != 'int':# 'attr' or node.left.object.type != 'local' or node.left.object.name != 'ARGV': # print('woah') pass else: node.right.value -= node.left.right.value node.left = node.left.left return '%s %s %s' % (self.binary_left(node, depth), node.op, self.binary_right(node, depth))
class CppGenerator(CodeGenerator): '''Cpp code generator''' indent = 4 use_spaces = True middlewares = [ DeclarationMiddleware, CppPointerMiddleware, CppDisplayExceptionMiddleware ] types = { 'Int': 'int', 'Float': 'float', 'Boolean': 'bool', 'String': 'string', 'List': 'vector<{0}>', 'Dictionary': 'unordered_map<{0}, {1}>', 'Tuple': lambda t: 'pair<{0}{1}>'.format(*t) if len(t) == 2 else 'tuple<{0}>'.format(', '.join(t)), 'Array': '{0}*', 'Set': 'set<{0}>', 'Void': 'void', 'Pointer': 'smart_ptr<{0}>' } templates = dict( module=''' %<dependencies:lines> %<#exception_dependencies> %<constants:lines> %<custom_exceptions:lines> %<definitions:lines> int main() { %<main:semi> } ''', function_definition=''' %<@return_type> %<name>(%<#params>) { %<block:semi> }''', method_definition=''' %<@return_type> %<name>(%<#params>) { %<block:semi> }''', class_definition=''' class %<name>%<.base> { %<attrs:lines> %<.constructor> %<methods:lines> }''', class_definition_base=(': %<base>', ''), class_definition_constructor=('%<constructor>', ''), class_attr='%<.is_public> %<@pseudo_type> %<name>;', class_attr_is_public=('public', 'private'), anonymous_function='[](%<#params>) %<#anon_block>', constructor=''' %<this>(%<#params>) { %<block:semi> }''', dependency='#include<%<name>>', local='%<name>', typename='%<name>', int='%<value>', float='%<value>', string='%<#safe_double>', boolean='%<value>', null='NULL', list="{%<elements:join ', '>}", dictionary="%<@pseudo_type>{{%<pairs:join ', '>}}", set="%<@pseudo_type>({%<elements:join ', '>})", regex='regex("%<value>")', pair="%<key>: %<value>", attr="%<object>.%<attr>", assignment=switch('first_mention', true='%<@value.pseudo_type> %<target> = %<value>', _otherwise='%<target> = %<value>'), binary_op='%<left> %<op> %<right>', unary_op='%<op>%<value>', comparison='%<left> %<op> %<right>', static_call="%<receiver>.%<message>(%<args:join ', '>)", call="%<function>(%<args:join ', '>)", method_call="%<receiver>.%<message>(%<args:join ', '>)", pointer_method_call="%<receiver>->%<message>(%<args:join ', '>)", this='this', instance_variable='this->%<name>', new_instance="new %<class_name>(%<args:join ', '>)", throw_statement='throw %<exception>(%<value>)', if_statement=''' if (%<test>) { %<block:semi> } %<.otherwise>''', if_statement_otherwise=('%<otherwise>', ''), elseif_statement=''' else if (%<test>) { %<block:semi> } %<.otherwise>''', elseif_statement_otherwise=('%<otherwise>', ''), else_statement=''' else { %<block:semi> }''', while_statement=''' while (%<test>) { %<block:semi> }''', try_statement=''' try { %<block:semi> } %<handlers:lines>''', exception_handler=''' catch (%<.exception>& %<instance>) { %<block:semi> }''', exception_handler_exception=('%<exception>', 'exception'), for_statement=switch(lambda f: f.iterators.type, for_iterator_with_index=''' for(int %<iterators.index> = 0; %<iterators.index> < %<sequences.sequence>.size(); %<iterators.index> ++) { auto %<iterators.iterator> = %<sequences.sequence>[%<iterators.index>]; %<block:semi> }''', for_iterator_zip=''' for(int _index = 0; _index < %<#first_sequence>.size(); _index ++) { %<#zip_iterators> %<block:semi> }''', for_iterator_with_items=''' for(auto& _item : %<sequences.sequence>) { auto %<iterators.key> = _item.first; auto %<iterators.value> = _item.second; %<block:semi> }''', _otherwise=''' for(%<iterators>: %<sequences>) { %<block:semi> }'''), for_range_statement=''' for(int %<index> = %<.first>; %<index> != %<end>; %<index> += %<.step>) { %<block:semi> }''', for_range_statement_first=('%<start>', '0'), for_range_statement_step=('%<step>', '1'), for_iterator='auto %<iterator>', for_iterator_zip="var %<iterators:join ', '>", for_iterator_with_index='int %<index>, var %<iterator>', for_iterator_with_items='%<key>, %<value>', for_sequence='%<sequence>', implicit_return='return %<value>', explicit_return='return %<value>', _with=''' with %<call> as %<context>: %<block:semi>''', index='%<sequence>[%<index>]', block='%<block:semi>', custom_exception=''' class %<name> : runtime_error { }''', _cpp_declaration='%<@decl_type> %<name>%<.args>', _cpp_declaration_args=("(%<args:join ', '>)", ''), _cpp_anon_declaration="%<@decl_type>(%<args:join ', '>)", _cpp_group='(%<value>)', _cpp_cin='cin >> %<args:first>', # support only one for now _cpp_cout="cout << %<args:join ' << '> << endl") def namespace(self, node, indent): return self.name.capitalize() def header(self, node, indent): return 'using System;\nnamespace %s;\n{\n' % self.namespace() def params(self, node, indent): return ', '.join( '%s %s' % (PseudoType('').expand_type(k.pseudo_type, self), k.name) for j, k in enumerate(node.params)) def anon_block(self, node, indent): if len(node.block) == 1: b = self._generate_node(node.block[0]) return '{ %s; }' % b else: b = ';\n'.join( self.offset(indent + 1) + self._generate_node(e, indent + 1) for e in node.block) + ';' return '{\n%s\n%s}' % (b, self.offset(indent)) def exception_dependencies(self, node, indent): if node.custom_exceptions: iostream = '' for d in node.dependencies: if d.name == 'iostream': break else: iostream = '#include<iostream>\n' return '%s#include<stdexcept>\n#include<exception>\n' % iostream else: return '' def zip_iterators(self, node, depth): return '\n'.join( '%sauto %s = %s;' % (self.offset(depth) if j else '', q.name, self._generate_node( Node('index', sequence=node.sequences.sequences[j], index=local('_index', 'Int'), pseudo_type=node.sequences.sequences[j].pseudo_type[1]))) for j, q in enumerate(node.iterators.iterators)) def first_sequence(self, node, depth): return self._generate_node(node.sequences.sequences[0])
class JSGenerator(CodeGenerator): '''JS generator''' indent = 2 use_spaces = True middlewares = [DeclarationMiddleware] templates = dict( module= "%<dependencies:lines>\n_ = require('lodash');\n%<constants:lines>%<custom_exceptions:lines>%<definitions:lines>%<main:semi>", function_definition=''' function %<name>(%<params:join ', '>) { %<block:semi> }''', method_definition=''' %<this>.prototype.%<name> = function (%<params:join ', '>) { %<block:semi> }''', class_definition=''' %<.constructor> %<.base> %<methods:lines>''', class_definition_base= ('%<name>.prototype = _.create(%<base>.prototype, {constructor: %<name>})', ''), class_definition_constructor=('%<constructor>', ''), dependency=switch('name', lodash="var _ = require('%<name>');", _otherwise="var %<name> = require('%<name>');"), anonymous_function=''' function (%<params:join ', '>) { %<block:semi> }''', constructor=''' function %<this>(%<params:join ', '>) { %<block:semi> }''', local='%<name>', typename='%<name>', int='%<value>', float='%<value>', string='%<#safe_single>', boolean='%<value>', null='null', list="[%<elements:join ', '>]", dictionary="{%<pairs:join ', '>}", pair=switch(lambda p: p.key.type == 'string' and JS_NAME.match( p.key.value) is not None, true='%<key.value>: %<value>', _otherwise='%<key>: %<value>'), attr="%<object>.%<attr>", custom_exception=''' function %<name>(message) { this.message = message; } %<name>.prototype = _.create(%<.base>.prototype, {constructor: %<name>});''', custom_exception_base=('%<base>', 'Error'), assignment=switch('first_mention', true='var %<target> = %<value>', _otherwise='%<target> = %<value>'), binary_op='%<#binary_left> %<#op> %<#binary_right>', unary_op='%<#op>%<value>', comparison='%<#comparison>', static_call="%<receiver>.%<message>(%<#args_join>)", call="%<function>(%<#args_join>)", method_call="%<receiver>.%<message>(%<#args_join>)", this_method_call="this.%<message>(%<#args_join>)", this='this', instance_variable='this.%<name>', throw_statement='throw new %<exception>(%<value>)', new_instance="new %<class_name>(%<args:join ', '>)", if_statement=''' if (%<test>) { %<block:semi> } %<.otherwise>''', if_statement_otherwise=(' %<otherwise>', ''), elseif_statement=''' else if (%<test>) { %<block:semi> } %<.otherwise>''', elseif_statement_otherwise=(' %<otherwise>', ''), else_statement=''' else { %<block:semi> }''', while_statement=''' while (%<test>) { %<block:semi> }''', try_statement=''' try { %<block:semi> } catch(%<#handler_>) { if %<handlers:join_depth_aware ' else if '> else { throw %<#handler_>; } }''', exception_handler=''' (%<instance> isinstanceof %<.is_builtin>) { %<block:semi> }''', # obvsly its an Error, but we'll have other builtin errors in next versions exception_handler_is_builtin=('Error', '%<exception>'), for_statement=''' _.forEach(%<sequences>, function (%<iterators>) { %<block:semi> })''', for_range_statement=''' for(var %<index> = %<.first>;%<index> != %<end>;%<index> += %<.step>) { %<block:semi> }''', for_range_statement_first=('%<start>', '0'), for_range_statement_step=('%<step>', '1'), for_iterator='%<iterator>', for_iterator_zip="%<iterators:join ', '>", for_iterator_with_index='%<iterator>, %<index>', for_iterator_with_items='%<value>, %<key>', for_sequence='%<sequence>', for_sequence_zip="_.zip(%<sequences:join ', '>)", for_sequence_with_index='%<sequence>', for_sequence_with_items='%<sequence>', tuple="[%<elements:join ', '>]", array="[%<elements:join ', '>]", set="{%<.elements>}", set_elements=("%<elements:join ': true, '>: true", ''), implicit_return='return %<value>', explicit_return='return %<value>', index=switch(index_switch, string='%<sequence>.%<index.value>', normal='%<sequence>[%<index>]', _otherwise='%<sequence>[%<sequence>.length - %<#index>]'), interpolation="%<args:join ' + '>", interpolation_literal='%<#safe_single>', interpolation_placeholder='%<value>', constant='%<constant> = %<init>', aug_assignment='%<target> += %<value>', standard_iterable_call=''' _.filter(%<sequences.sequence>, function (%<iterators>) { return %<test:first>; }).map(function (%<iterators>) { return %<block:first>; })''', block='%<block:semi>', not_null_check='%<value>', regex='/%<value>/', ) def handler_(self, node, indent): if node.handlers: return node.handlers[0].instance else: return '_e' def op(self, node, depth): return OPS.get(node.op, node.op) def args_join(self, node, depth): return ', '.join( self._generate_node(n, depth).lstrip() for n in node.args) def comparison(self, node, depth): if node.left.type == 'binary_op' and node.left.op == '-' and node.left.right.type == 'int' and node.right.type == 'int': node.right.value += node.left.right.value node.left = node.left.left if node.op == '==' and isinstance( node.left.pseudo_type, list) and node.left.pseudo_type[0] == 'List': return '_.isEqual(%s, %s)' % (self.binary_left( node, depth), self.binary_right(node, depth)) return '%s %s %s' % (self.binary_left( node, depth), node.op, self.binary_right(node, depth)) def index(self, node, depth): return str(-node.index.value)
class PythonGenerator(CodeGenerator): '''Python code generator''' indent = 4 use_spaces = True middlewares = [] templates = dict( module = ''' %<dependencies:lines> %<constants:lines> %<custom_exceptions:lines> %<definitions:lines> %<main:lines>''', function_definition = ''' def %<name>(%<params:join ', '>): %<block:line_join_pass>''', function_definition_block = ("%<block:line_join>", 'pass'), method_definition = ''' def %<name>(self%<params:each_lpad ', '>): %<block:line_join_pass>''', method_definition_block = ('%<block:line_join>', 'pass'), class_definition = ''' class %<name>%<.base>: %<.constructor> %<methods:line_join> %<#class_pass>''', class_definition_base = ('(%<base>)', ''), class_definition_constructor = ('%<constructor>', ''), new_instance = "%<class_name>(%<args:join ', '>)", anonymous_function = '%<#anonymous_function>', constructor = ''' def __init__(self%<.params>): %<block:line_join_pass>''', constructor_params = ("%<params:each_lpad ', '>", ''), dependency = 'import %<name>', local = '%<name>', typename = '%<name>', int = '%<value>', float = '%<value>', string = '%<#safe_single>', boolean = '%<#to_boolean>', null = 'None', list = "[%<elements:join ', '>]", dictionary = "{%<pairs:join ', '>}", pair = "%<key>: %<value>", attr = "%<object>.%<attr>", assignment = '%<target> = %<value>', operation_assign = '%<slot> %<op>= %<value>', binary_op = '%<#binary_left> %<op> %<#binary_right>', unary_op = switch(lambda u: u.op == 'not', true = 'not %<value>', _otherwise = '%<op>%<value>' ), comparison = '%<#binary_left> %<op> %<#binary_right>', _py_del = 'del %<value>', _py_setitem = '%<sequence>[%<key>] = %<value>', _py_slice = '%<sequence>[%<from_>:%<to>]', _py_slice_from = '%<sequence>[%<from_>:]', _py_slice_to = '%<sequence>[:%<to>]', static_call = switch(lambda s: len(s.args) == 1 and s.args[0].type == '_py_generatorcomp', true = '%<receiver>.%<message>%<args:first>', _otherwise = "%<receiver>.%<message>(%<args:join ', '>)"), call = switch(lambda s: len(s.args) == 1 and s.args[0].type == '_py_generatorcomp', true = '%<function>%<args:first>', _otherwise = "%<function>(%<args:join ', '>)"), method_call = switch(lambda s: len(s.args) == 1 and s.args[0].type == '_py_generatorcomp', true = '%<receiver>.%<message>%<args:first>', _otherwise = "%<receiver>.%<message>(%<args:join ', '>)"), this_method_call = switch(lambda s: len(s.args) == 1 and s.args[0].type == '_py_generatorcomp', true = 'self.%<message>%<args:first>', _otherwise = "self.%<message>(%<args:join ', '>)"), block = '%<block:lines>', this = 'self', instance_variable = 'self.%<name>', throw_statement = 'raise %<exception>(%<value>)', if_statement = ''' if %<test>: %<block:line_join_pass> %<.otherwise>''', if_statement_otherwise = ('%<otherwise>', ''), elseif_statement = ''' elif %<test>: %<block:line_join_pass> %<.otherwise>''', elseif_statement_otherwise = ('%<otherwise>', ''), else_statement = ''' else: %<block:line_join_pass>''', while_statement = ''' while %<test>: %<block:line_join_pass>''', try_statement = ''' try: %<block:line_join_pass> %<handlers:lines>''', exception_handler = ''' except %<.is_builtin> as %<instance>: %<block:line_join_pass>''', exception_handler_is_builtin = ('Exception', '%<exception>'), for_statement = ''' for %<iterators> in %<sequences>: %<block:line_join_pass>''', for_range_statement = ''' for %<index> in range(%<.first>%<end>%<.step>): %<block:line_join_pass>''', for_range_statement_first = ('%<start>, ', '%<start>, '), for_range_statement_step = (', %<step>', ''), implicit_return = 'return %<value>', explicit_return = 'return %<value>', _py_with = ''' with %<call> as %<context>: %<block:line_join_pass>''', custom_exception = ''' class %<name>(%<.base>): pass''', custom_exception_base = ('%<base>', 'Exception'), constant = '%<constant> = %<init>', # standard_iterable_call = switch('function', # map = '[%<.block>]', # filter_map = "[%<.block> if %<test:join ''>]", # _otherwise = '%<function>([%<.block>])' # ), # standard_iterable_call_range = "[%<block:join ''> for %<index> in range(%<.first>%<last>%<.step>)]", # standard_iterable_call_block = ("%<block:join ''> for %<iterators> in %<sequences>", ''), # standard_iterable_call_first = ('%<first>, ', ''), # standard_iterable_call_step = (', %<step>', ''), for_iterator = '%<iterator>', for_iterator_zip = "%<iterators:join ', '>", for_iterator_with_index = '%<index>, %<iterator>', for_iterator_with_items = '%<key>, %<value>', for_sequence = '%<sequence>', for_sequence_zip = "zip(%<sequences:join ', '>)", for_sequence_with_index = 'enumerate(%<sequence>)', for_sequence_with_items = '%<sequence>.items()', tuple = "(%<elements:join ', '>)", array = "(%<elements:join ', '>)", set = '%<.elements>', set_elements = ( "{%<elements:join ', '>}", 'set()' ), index = '%<sequence>[%<index>]', interpolation = "'%<args:join ''>'.format(%<#placeholders>)", interpolation_literal = '%<value>', break_ = 'break', interpolation_placeholder = '{%<index>}', _py_listcomp = '[%<block> for %<iterators> in %<sequences>%<#test>]', _py_generatorcomp = '(%<block> for %<iterators> in %<sequences>%<#test>)', _py_in = '%<value> in %<sequence>', _py_step = '%<sequence>[::%<step>]', not_null_check = '%<value> is not None', aug_assignment = '%<target> %<op>= %<value>', standard_iterable_call = '[%<block:first> for %<iterators> in %<sequences> if %<test:first>]', regex = "re.compile(r'%<value>')", ) def to_boolean(self, node, indent): if node.value == 'true': return 'True' else: return 'False' def block(self, node, indent): if node.block: e = self._generate_node(node.block[0]) other = [self.offset(indent) + self._generate_node(n, indent) for n in node.block[1:]] return '\n'.join([e] + other) else: return 'pass' def anonymous_function(self, node, indent): params = ', '.join(map(self._generate_node, node.params)) lambda_head = 'lambda%s:' % (' ' + params if params else '') if not node.block: return '%s pass' % lambda_head elif len(node.block) == 1 and node.block[0].type in EXPRESSION_TYPES: if node.block[0].type == 'implicit_return' or node.block[0].type == 'explicit_return': block = node.block[0].value else: block = node.block[0] return '%s %s' % (lambda_head, self._generate_node(block)) else: name = 'a_%d' % len(self.a) block = [self.offset(1) + self._generate_node(z) for z in node.block] code = 'def %s(%s):\n%s\n' % (name, params, '\n'.join(block)) self.a.append(code) return name def class_pass(self, node, indent): if not node.constructor and not node.methods: return 'pass' else: return '' def test(self, node, indent): if node.test: return ' if %s' % self._generate_node(node.test) else: return '' def placeholders(self, node, indent): return ', '.join(self._generate_node(placeholder.value) for placeholder in node.args[1::2])
class CSharpGenerator(CodeGenerator): '''CSharp code generator''' indent = 4 use_spaces = True middlewares = [ TupleMiddleware(all=False), DeclarationMiddleware, NameMiddleware(normal_name='camel_case', method_name='pascal_case', function_name='pascal_case') ] types = { 'Int': 'int', 'Float': 'float', 'Boolean': 'bool', 'String': 'string', 'List': 'List<{0}>', 'Dictionary': 'Dictionary<{0}, {1}>', 'Set': 'HashSet<{0}>', 'Tuple': lambda x: 'Tuple<{0}>'.format(', '.join(x)), 'Array': '{0}[]', # fixed-size buffers in c# are not widely used # they require a struct and an unsafe annotation # we can a unsafe-fixed-size-buffer option to config 'Void': 'void', 'Regexp': 'Regex', 'RegexpMatch': 'Match' } templates = dict( module=''' using System; %<dependencies:lines> %<custom_exceptions:lines> %<tuple_definitions:lines> %<#class_definitions> public class Program { %<constants:lines> %<#function_definitions> public static void Main(string[] args) { %<main:semi> } }''', function_definition=''' static %<@return_type> %<name>(%<#params>) { %<block:semi> }''', method_definition=''' %<.is_public> %<@return_type> %<name>(%<#params>) { %<block:semi> }''', method_definition_is_public=('public', 'private'), class_definition=''' public class %<name>%<.base> { %<attrs:lines> %<.constructor> %<methods:line_join> }''', class_definition_base=('%<#base>', ''), class_definition_constructor=('%<constructor>', ''), class_attr="%<.is_public>%<@pseudo_type> %<name:camel_case 'lower'>;", class_attr_is_public=('public ', 'private '), immutable_class_attr=''' private readonly %<@pseudo_type> %<name>; public %<@pseudo_type> %<name:camel_case 'title'> { get { return %<name>; } }''', anonymous_function="%<#anon_params> =>%<#anon_block>", constructor=''' public %<this>(%<#params>) { %<block:semi> }''', dependency='using %<name>;', local='%<name>', typename='%<name>', int='%<value>', float='%<value>', string='%<#safe_double>', boolean='%<value>', null='null', simple_initializer="new %<name>(%<args:join ', '>)", list=switch(lambda l: len(l.elements) > 0, true="new[] {%<elements:join ', '>}", _otherwise="Enumerable.Empty<int>()"), dictionary=switch(lambda d: len(d.pairs) > 0, true="new %<@pseudo_type> { %<pairs:join ', '> }", _otherwise="new Dictionary<int, int> {}"), pair="{%<key>, %<value>}", attr="%<object>.%<attr>", new_instance="new %<class_name>(%<args:join ', '>)", # assignment = '%<#z>', assignment=switch( 'first_mention', true= 'var %<target> = %<value>', # in v0.3 add config/use var only for generic types _otherwise='%<target> = %<value>'), tuple=switch(lambda e: len(e.elements) <= 2, true="Tuple.Create(%<elements:join ', '>)", _otherwise=''' Tuple.Create( %<elements:c_lines> )'''), array="new[] { %<elements:join ', '> }", set=switch(lambda s: len(s.elements) > 0, true="new %<@pseudo_type>(new[] {%<elements:join ', '>})", _otherwise="new HashSet<int>()"), char="%<#char>", binary_op='%<#binary_left> %<#op> %<#binary_right>', unary_op='%<#op>%<value>', comparison='%<#comparison>', static_call="%<receiver>.%<message>(%<args:join ', '>)", call="%<function>(%<args:join ', '>)", method_call="%<receiver>.%<message>(%<args:join ', '>)", this_method_call= "this.%<message:camel_case 'title'>(%<args:join ', '>)", this='this', instance_variable='this.%<name>', throw_statement='throw new %<exception>(%<value>)', if_statement=''' if (%<test>) { %<block:semi> } %<.otherwise>''', if_statement_otherwise=('%<otherwise>', ''), elseif_statement=''' else if (%<test>) { %<block:semi> } %<.otherwise>''', elseif_statement_otherwise=('%<otherwise>', ''), else_statement=''' else { %<block:semi> }''', while_statement=''' while (%<test>) { %<block:semi> }''', try_statement=''' try { %<block:semi> } %<handlers:lines>''', exception_handler=''' catch (%<.exception> %<instance>) { %<block:semi> }''', exception_handler_exception=('%<exception>', 'Exception'), for_each_statement=''' for %<iterator> in %<sequence>: %<#block>''', for_each_with_index_statement=''' for %<index>, %<iterator> in %<.sequence>: %<#block>''', for_each_with_index_statement_sequence=('%<#index_sequence>', ''), for_each_in_zip_statement=''' for %<iterators:join ', '> in zip(%<sequences:join ', '>): %<#block>''', implicit_return='return %<value>', explicit_return='return %<value>', index=switch(index_switch, tuple='%<sequence>.Item%<#tuple_index>', normal='%<sequence>[%<index>]', _otherwise='%<sequence>[%<sequence>.Length - %<#index>]'), interpolation="string.Format(\"%<args:join ''>\", %<#placeholders>)", interpolation_placeholder="{%<index>}", interpolation_literal="%<value>", index_assignment='%<sequence>[%<index>] = %<value>', not_null_check='%<value> != null', constant='%<constant> = %<init>', for_statement=switch(lambda f: f.iterators.type, for_iterator_with_index=''' for (int %<iterators.index> = 0; %<iterators.index> < %<sequences.sequence>.Length; %<iterators.index> ++) { var %<iterators.iterator> = %<sequences.sequence>[%<iterators.index>]; %<block:semi> }''', for_iterator_zip=''' for (int _index = 0; _index < %<#first_sequence>.Length; _index ++) { %<#zip_iterators> %<block:semi> }''', for_iterator_with_items=''' foreach(var _item in %<sequences.sequence>) { var %<iterators.key> = _item.key; var %<iterators.value> = _item.value; %<block:semi> }''', _otherwise=''' foreach(%<iterators> in %<sequences>) { %<block:semi> }'''), for_range_statement=''' for (int %<index> = %<.first>; %<index> != %<last>; %<index> += %<.step>) { %<block:semi> }''', for_range_statement_first=('%<first>', '0'), for_range_statement_step=('%<step>', '1'), for_iterator='var %<iterator>', for_iterator_zip="var %<iterators:join ', '>", for_iterator_with_index='int %<index>, var %<iterator>', for_iterator_with_items='%<key>, %<value>', for_sequence='%<sequence>', custom_exception=''' public class %<name> : Exception { public %<name>(string message) : base(message) { } }''', standard_iterable_call=''' %<sequences> .Where(%<iterators.iterator> => %<test:first>) .Select(%<iterators.iterator> => %<block:first>) .ToList()''', aug_assignment='%<target> %<op>= %<value>', block='%<block:semi>', regex='@"%<value>') def params(self, node, indent): return ', '.join( '%s %s' % (self.render_type(node.pseudo_type[j + 1]), self._generate_node(k)) for j, k in enumerate(node.params)) def anon_params(self, node, indent): if len(node.params) == 0: return '' else: l, r = ('(', ')') if len(node.params) > 1 else ('', '') return '%s%s%s' % (l, ', '.join( param if isinstance(param, str) else self._generate_node(param) for param in node.params), r) def anon_block(self, node, indent): # print(indent);input(node.params[0].y) if indent < 2: indent = 2 # anon cant be before method lvl if len(node.block) == 1: if node.block[0].type == 'implicit_return' or node.block[ 0].type == 'explicit_return': e = node.block[0].value else: e = node.block[0] b = self._generate_node(e) return ' ' + b else: b = ';\n'.join( self.offset(indent + 1) + self._generate_node(e, indent + 1) for e in node.block) + ';\n' return ' {\n%s%s}' % (b, self.offset(indent)) def class_definitions(self, node, depth): result = '\n'.join( self._generate_node(k) for k in node.definitions if k.type == 'class_definition') if result: return result + '\n' else: return '' def function_definitions(self, node, depth): result = '\n'.join( self.offset(1) + self._generate_node(f, 1) for f in node.definitions if f.type == 'function_definition') if result: return result + '\n' else: return '' def base(self, node, depth): if node.base: return ' : %s' % node.base else: return '' def first_sequence(self, node, depth): return self._generate_node(node.sequences.sequences[0]) def zip_iterators(self, node, depth): return '\n'.join( '%svar %s = %s;' % (self.offset(depth) if j else '', q.name, self._generate_node( Node('index', sequence=node.sequences.sequences[j], index=local('_index', 'Int'), pseudo_type=node.sequences.sequences[j].pseudo_type[1]))) for j, q in enumerate(node.iterators.iterators)) def tuple_index(self, node, depth): return str(node.index.value + 1) def op(self, node, depth): return OPS.get(node.op, node.op) def char(self, node, depth): if node.value == "'": return "'\\''" else: return "'%s'" % node.value # args starting from 0 def comparison(self, node, depth): if node.left.type != 'binary_op' or node.left.op != '+' or node.left.right.type != 'int' or node.right.type != 'int': # 'attr' or node.left.object.type != 'local' or node.left.object.name != 'ARGV': pass else: node.right.value -= node.left.right.value node.left = node.left.left return '%s %s %s' % (self.binary_left( node, depth), node.op, self.binary_right(node, depth)) def z(self, node, depth): print(node.y) input() return '!!!' def index(self, node, depth): return str(-node.index.value) def placeholders(self, node, depth): return ', '.join( self._generate_node(child.value) for child in node.args[1::2])
class GolangGenerator(CodeGenerator): '''Go generator''' indent = 1 use_spaces = False middlewares = [ TupleMiddleware(True), GoConstructorMiddleware, DeclarationMiddleware, NameMiddleware(normal_name='camel_case', method_name='pascal_case', function_name='pascal_case', attr_name='pascal_case'), StandardMiddleware ] # GoErrorHandlingMiddleware types = { 'Int': 'int', 'Float': 'float', 'Boolean': 'bool', 'String': 'string', 'List': '[]{0}', 'Dictionary': 'map[{0}]{1}', 'Set': 'map[{0}]struct{}', 'Tuple': lambda x: safe_serialize_type(['Tuple'] + x), # uh yea, in next version we'll add some kind of smart-name / config option 'Array': '[{1}]{0}', 'Void': 'void', 'Regexp': '*regexp.Regexp', 'RegexpMatch': '[][][]byte' } templates = dict( module=''' package main %<#dependencies> %<constants:lines> %<custom_exceptions:lines> %<definitions:lines> %<tuple_definitions:line_join> func main() { %<main:line_join> }''', function_definition=''' func %<name>(%<#params>) %<#return_type> { %<block:line_join> }''', method_definition=''' func (this *%<this>) %<name>(%<#params>) %<#return_type> { %<block:line_join> }''', class_definition=''' type %<name> struct { %<.base> %<attrs:line_join> } %<.constructor> %<methods:line_join>''', class_definition_base=('extend %<base>', ''), class_definition_constructor=('%<constructor>', ''), class_attr=switch('is_public', true="%<name> %<@pseudo_type>", _otherwise="%<name> %<@pseudo_type>"), immutable_class_attr="%<name:camel_case 'title'> %<@pseudo_type>", anonymous_function=switch(lambda a: len(a.block) == 1, true='func (%<#params>) { %<block:first> }', _otherwise=''' func (%<#params>) { %<block:line_join> }'''), constructor=''' func new%<this>(%<#params>) *%<this> { %<block:line_join> }''', new_instance="new%<class_name>(%<args:join ', '>)", _go_bytes='[]byte(%<value>)', _go_make_slice='make(%<@slice_type>, %<#initial>, %<length>)', _go_simple_initializer="%<name>{%<args:join ', '>}", _go_declaration='var %<decl> %<@decl_type>', dependency='"%<name>"', break_='break', local='%<name>', typename='%<name>', int='%<value>', float='%<value>', string='%<#safe_double>', boolean='%<value>', null='nil', list=switch(lambda l: len(l.elements) > 0, true="%<@pseudo_type> {%<elements:join ', '>}", _otherwise="[]int {}"), dictionary=switch(lambda l: len(l.pairs) > 0, true="%<@pseudo_type> { %<pairs:join ', '> }", _otherwise="map[int]int {}"), pair="%<key>: %<value>", attr="%<object>.%<attr>", array="[...]%<#element_type>{%<elements:join ', '>}", _go_slice='%<sequence>[%<from_>:%<to>]', _go_slice_from='%<sequence>[%<from_>:]', _go_slice_to='%<sequence>[:%<to>]', assignment=switch('first_mention', true='%<target> := %<value>', _otherwise='%<target> = %<value>'), _go_multi_assignment=switch( 'first_mention', true="%<targets:join ', '> := %<values:join ', '>", _otherwise="%<targets:join ', '> = %<values:join ', '>"), _go_ref='&%<value>', binary_op='%<#binary_left> %<#op> %<#binary_right>', unary_op='%<#op>%<value>', comparison='%<#binary_left> %<op> %<#binary_right>', set=switch(lambda l: len(l.elements) > 0, true="%<@pseudo_type> { #set_pairs }", _otherwise="map[int]struct{} {}"), static_call="%<receiver>.%<message>(%<args:join ', '>)", call="%<function>(%<args:join ', '>)", method_call="%<receiver>.%<message>(%<args:join ', '>)", this_method_call="this.%<message>(%<args:join ', '>)", this='this', instance_variable='this.%<name>', not_null_check='false', #'%<value> != nil', throw_statement='throw %<exception>(%<value>)', if_statement=''' if %<test> { %<block:line_join> } %<.otherwise>''', if_statement_otherwise=('%<otherwise>', ''), elseif_statement=''' else if %<test> { %<block:line_join> } %<.otherwise>''', elseif_statement_otherwise=('%<otherwise>', ''), else_statement=''' else { %<block:line_join> }''', while_statement=''' for %<test> { %<block:line_join> }''', # try_statement = ''' # try # { # %<block:semi> # } # %<handlers:lines>''', # exception_handler = ''' # except %<exception> as %<instance> # { # %<block:semi>''', for_statement=switch(lambda f: f.iterators.type, for_iterator_zip=''' for _index, _ := range %<sequences> { %<#zip_iterators> %<block:line_join> } ''', _otherwise=''' for %<iterators> := range %<sequences> { %<block:line_join> }'''), for_range_statement=''' for %<index> := %<.first>; %<index> != %<end>; %<index> += %<.step> { %<block:line_join> }''', for_range_statement_first=('%<start>', '0'), for_range_statement_step=('%<step>', '1'), for_iterator='_, %<iterator>', for_iterator_zip='%<#zip_iterators>', for_iterator_with_index='%<index>, %<iterator>', for_iterator_with_items='%<key>, %<value>', for_sequence='%<sequence>', for_sequence_zip='len(%<sequences:first>)', for_sequence_with_index='%<sequence>', for_sequence_with_items='%<sequence>', implicit_return='return %<value>', explicit_return='return %<value>', aug_assignment='%<target> %<op>= %<value>', index=switch(lambda i: i.index.type != 'int' or i.index.value >= 0, true='%<sequence>[%<index>]', _otherwise='%<sequence>[len(%<sequence>) - %<#index>]'), interpolation="fmt.Sprintf(\"%<args:join ''>\", %<#placeholderz>)", interpolation_literal='%<value>', interpolation_placeholder=switch(lambda i: i.pseudo_type == 'Int', true='%d', _otherwise='%s'), index_assignment='%<sequence>[%<index>] = %<value>', constant='%<constant> = %<init>', custom_exception=''' class %<name> : Exception ''', simple_initializer="%<name>{%<args:join ', '>}", standard_iterable_call=''' var _results %<@pseudo_type> for %<iterators> := range %<sequences> { if %<test:first> { _results = append(_results, %<block:first>) } } _results''', standard_iterable_call_return=''' var _results %<@pseudo_type> for %<iterators> := range %<sequences> { if %<test:first> { _results = append(_results, %<block:first>) } } return _results''', block='%<block:line_join>', regex='"%<value>"', ) def params(self, node, depth): return ', '.join( '%s %s' % (self._generate_node(k), self.render_type(node.pseudo_type[j + 1])) for j, k in enumerate(node.params)) def dependencies(self, node, depth): if len(node.dependencies) == 1: return 'import "%s"' % node.dependencies[0].name elif len(node.dependencies) > 1: return 'import (\n\t%s\n)\n' % '\n\t'.join( '"%s"' % q.name for q in node.dependencies) else: return '' def element_type(self, node, _): return PseudoType('').expand_type(node.pseudo_type[1], self) def op(self, node, depth): return OPS.get(node.op, node.op) # keys in pseudo can be only string or int float bool def initial(self, node, _): '''initial value for make''' return { 'Int': '0', 'Float': '0.0', 'String': '""', 'Bool': 'true' }.get(node.slice_type[1], 'nil') def zip_iterators(self, node, depth): return '\n'.join( '%s%s := %s' % (self.offset(depth) if j else '', q.name, self._generate_node( Node('index', sequence=node.sequences.sequences[j], index=local('_index', 'Int'), pseudo_type=node.sequences.sequences[j].pseudo_type[1]))) for j, q in enumerate(node.iterators.iterators)) def placeholderz(self, node, _): return ', '.join( self._generate_node(placeholder.value) for placeholder in node.args[1::2]) def index(self, node, depth): return str(-node.index.value) def return_type(self, node, depth): format = self.render_type(node.return_type) if isinstance(node.return_type, list) or node.return_type in self.types: return format else: return '*%s' % format