def body(stmnt, symbol_table, end_switch): symbol_table = push(symbol_table) stack, statement = imap(symbol_table.__getitem__, ('__ stack __', '__ statement __')) symbol_table['__ break __'] = (end_switch, stack.stack_pointer) symbol_table['__ switch __'] = True allocation_table = [] # create an allocation table to update stack before jump in case of nested definitions switch_body_instrs = [] cases = {'default': Offset(end_switch, loc(stmnt))} for instr in statement(stmnt.statement, symbol_table): if isinstance(getattr(instr, 'case', None), CaseStatement): start = Pass(loc(instr)) allocation_table.append( chain( (start,), update_stack(stmnt.stack.stack_pointer, instr.case.stack.stack_pointer, loc(instr)), relative_jump(Offset(instr, loc(instr)), loc(instr)), ) ) cases[error_if_not_type(exp(exp(instr.case)), (int, long, str))] = Offset(start, loc(instr)) del instr.case switch_body_instrs.append(instr) max_switch_value = 2**(8*size_arrays_as_pointers(c_type(exp(stmnt)))) - 1 for instr in jump_table(loc(stmnt), cases, allocation_table, max_switch_value, switch_body_instrs): yield instr _ = pop(symbol_table)
def comma_expression(expr, symbol_table): expression = symbol_table['__ expression __'] return chain( chain.from_iterable( chain( expression(e, symbol_table), allocate( -size_arrays_as_pointers(c_type(e), overrides={VoidType: 0}), loc(e))) for e in exp(expr)[:-1]), expression(exp(expr)[-1], symbol_table))
def constant_expression(tokens, symbol_table): _exp = symbol_table['__ logical_or_expression __'](tokens, symbol_table) # ENUM types ... if isinstance(_exp, IdentifierExpression) and isinstance(symbol_table.get(exp(_exp), type), ConstantExpression): _exp = symbol_table[exp(_exp)] if not isinstance(_exp, ConstantExpression): raise ValueError('{l} Expected a constant expression got {got}'.format(l=loc(_exp), got=_exp)) return _exp
def numeric_operator(value, expr, symbol_table): return symbol_table['__ expression __']( BinaryExpression( ConstantExpression(value, IntegerType(loc(expr)), loc(expr)), TOKENS.STAR, exp(expr), max(c_type(exp(expr)), IntegerType(loc(expr)))(loc(expr)), loc(expr), ), symbol_table, )
def numeric_operator(value, expr, symbol_table): return symbol_table['__ expression __']( BinaryExpression( ConstantExpression(value, IntegerType(loc(expr)), loc(expr)), TOKENS.STAR, exp(expr), max(c_type(exp(expr)), IntegerType(loc(expr)))(loc(expr)), loc(expr), ), symbol_table, )
def binary_exp(expr): if not all(imap(isinstance, (left_exp(expr), right_exp(expr)), repeat(ConstantExpression))): return expr exp_type = max(imap(c_type, (left_exp(expr), right_exp(expr))))(loc(expr)) l_exp, r_exp, location = exp(left_exp(expr)), exp(right_exp(expr)), loc(expr) # noinspection PyUnresolvedReferences '1 + 2 - 3 * 7 / 4' return binary_exp.rules[oper(expr)]( expr=expr, left_exp=l_exp, right_exp=r_exp, location=location, exp_type=exp_type )
def comma_expression(expr, symbol_table): expression = symbol_table['__ expression __'] return chain( chain.from_iterable( chain( expression(e, symbol_table), allocate(-size_arrays_as_pointers(c_type(e), overrides={VoidType: 0}), loc(e)) ) for e in exp(expr)[:-1] ), expression(exp(expr)[-1], symbol_table) )
def while_statement(stmnt, symbol_table): start_of_loop, end_of_loop = imap(Pass, repeat(loc(stmnt), 2)) return chain( (start_of_loop,), get_jump_false(size_arrays_as_pointers(c_type(exp(stmnt))))( symbol_table['__ expression __'](exp(stmnt), symbol_table), Offset(end_of_loop, loc(end_of_loop)), loc(end_of_loop) ), loop_body(stmnt.statement, symbol_table, start_of_loop, end_of_loop), relative_jump(Offset(start_of_loop, loc(start_of_loop)), loc(end_of_loop)), (end_of_loop,) )
def do_while_statement(stmnt, symbol_table): start_of_loop, end_of_loop = Pass(loc(stmnt)), Pass(loc(stmnt)) yield start_of_loop # do while loops contain the update expression after their body ... for instr in loop_body(stmnt.statement, symbol_table, start_of_loop, end_of_loop): yield instr for instr in get_jump_true(size_arrays_as_pointers(c_type(exp(stmnt))))( symbol_table['__ expression __'](exp(stmnt), symbol_table), Offset(start_of_loop, loc(start_of_loop)), loc(start_of_loop) ): yield instr yield end_of_loop
def constant_expression(tokens, symbol_table): _exp = symbol_table['__ logical_or_expression __'](tokens, symbol_table) # ENUM types ... if isinstance(_exp, IdentifierExpression) and isinstance( symbol_table.get(exp(_exp), type), ConstantExpression): _exp = symbol_table[exp(_exp)] if not isinstance(_exp, ConstantExpression): raise ValueError('{l} Expected a constant expression got {got}'.format( l=loc(_exp), got=_exp)) return _exp
def dimensions(tokens): while peek(tokens) == TOKENS.LEFT_BRACKET: location = loc(consume(tokens)) if peek(tokens) == TOKENS.RIGHT_BRACKET: size = None else: const_exp = constant_expression(tokens, symbol_table) _ = error_if_not_type(c_type(const_exp), IntegralType) if exp(const_exp) < 0: raise ValueError('{l} array size is negative'.format(l=loc(const_exp))) size = exp(const_exp) _ = error_if_not_value(tokens, TOKENS.RIGHT_BRACKET) yield size, location
def dimensions(tokens): while peek(tokens) == TOKENS.LEFT_BRACKET: location = loc(consume(tokens)) if peek(tokens) == TOKENS.RIGHT_BRACKET: size = None else: const_exp = constant_expression(tokens, symbol_table) _ = error_if_not_type(c_type(const_exp), IntegralType) if exp(const_exp) < 0: raise ValueError( '{l} array size is negative'.format(l=loc(const_exp))) size = exp(const_exp) _ = error_if_not_value(tokens, TOKENS.RIGHT_BRACKET) yield size, location
def ternary_expression(expr, symbol_table): if_false_instr, end_of_conditional_instr = Pass(loc(expr)), Pass(loc(expr)) expression = symbol_table['__ expression __'] return chain( get_jump_false(size_arrays_as_pointers(c_type(exp(expr))))( expression(exp(expr), symbol_table), Offset(if_false_instr, loc(expr)), loc(expr) ), expression(left_exp(expr), symbol_table), relative_jump(Offset(end_of_conditional_instr, loc(end_of_conditional_instr)), loc(expr)), (if_false_instr,), expression(right_exp(expr), symbol_table), (end_of_conditional_instr,), )
def ternary_expression(expr, symbol_table): if_false_instr, end_of_conditional_instr = Pass(loc(expr)), Pass(loc(expr)) expression = symbol_table['__ expression __'] return chain( get_jump_false(size_arrays_as_pointers(c_type(exp(expr))))(expression( exp(expr), symbol_table), Offset(if_false_instr, loc(expr)), loc(expr)), expression(left_exp(expr), symbol_table), relative_jump( Offset(end_of_conditional_instr, loc(end_of_conditional_instr)), loc(expr)), (if_false_instr, ), expression(right_exp(expr), symbol_table), (end_of_conditional_instr, ), )
def switch_statement(stmnt, symbol_table): _ = (not isinstance(c_type(exp(stmnt)), IntegralType)) and raise_error( '{l} Expected an integral type got {g}'.format(g=c_type(exp(stmnt)), l=loc(stmnt))) end_switch = Pass(loc(stmnt)) stmnt.stack = deepcopy(symbol_table['__ stack __']) # if switch inside loop, only update end_instruct, since continue jumps to start of loop break goes to end of switch def body(stmnt, symbol_table, end_switch): symbol_table = push(symbol_table) stack, statement = imap(symbol_table.__getitem__, ('__ stack __', '__ statement __')) symbol_table['__ break __'] = (end_switch, stack.stack_pointer) symbol_table['__ switch __'] = True allocation_table = [ ] # create an allocation table to update stack before jump in case of nested definitions switch_body_instrs = [] cases = {'default': Offset(end_switch, loc(stmnt))} for instr in statement(stmnt.statement, symbol_table): if isinstance(getattr(instr, 'case', None), CaseStatement): start = Pass(loc(instr)) allocation_table.append( chain( (start, ), update_stack(stmnt.stack.stack_pointer, instr.case.stack.stack_pointer, loc(instr)), relative_jump(Offset(instr, loc(instr)), loc(instr)), )) cases[error_if_not_type(exp(exp(instr.case)), (int, long, str))] = Offset( start, loc(instr)) del instr.case switch_body_instrs.append(instr) max_switch_value = 2**(8 * size_arrays_as_pointers(c_type(exp(stmnt)))) - 1 for instr in jump_table(loc(stmnt), cases, allocation_table, max_switch_value, switch_body_instrs): yield instr _ = pop(symbol_table) return chain(symbol_table['__ expression __'](exp(stmnt), symbol_table), body(stmnt, symbol_table, end_switch), (end_switch, ))
def update_scalar_type_initializer(desig_expr, default_values): assert len(default_values) == 1 expr, desig = exp(desig_expr), designation(desig_expr, 0) if desig != 0: logger.warning('Excess Elements in initializer ...') else: default_values[0] = cast(expr, c_type(default_values[0]))
def update_scalar_type_initializer(desig_expr, default_values): assert len(default_values) == 1 expr, desig = exp(desig_expr), designation(desig_expr, 0) if desig != 0: logger.warning('Excess Elements in initializer ...') else: default_values[0] = cast(expr, c_type(default_values[0]))
def init_declarator(tokens, symbol_table, base_type=CType(''), storage_class=None): # : declarator ('=' assignment_expression or initializer)? decl = set_core_type( symbol_table['__ declarator __'](tokens, symbol_table), base_type) if peek_or_terminal(tokens) == TOKENS.EQUAL and consume(tokens): decl = Definition(name(decl), c_type(decl), EmptyExpression(c_type(decl)), loc(decl), storage_class) symbol_table[name( decl )] = decl # we have to add it to the symbol table for things like `int a = a;` expr = initializer_or_assignment_expression(tokens, symbol_table) # if declaration is an array type and the expression is of string_type then convert to initializer for parsing if isinstance(c_type(decl), ArrayType) and isinstance( c_type(expr), StringType): expr = Initializer( enumerate(exp(expr)), ArrayType(c_type(c_type(expr)), len(c_type(expr)), loc(expr)), loc(expr)) decl.initialization = parse_initializer(expr, decl) if isinstance( expr, Initializer) else expr else: symbol_table[name(decl)] = decl = Declaration(name(decl), c_type(decl), loc(decl)) return decl
def update_composite_type_initializer(desig_expr, default_values): desig = designation(desig_expr) if desig > default_values: logger.warning('Excess elements in initializer ...') else: assert len(default_values[desig]) == 1 default_values[desig][0] = cast(exp(desig_expr), c_type(default_values[desig][0]))
def binary_exp(expr): if not all( imap(isinstance, (left_exp(expr), right_exp(expr)), repeat(ConstantExpression))): return expr exp_type = max(imap(c_type, (left_exp(expr), right_exp(expr))))(loc(expr)) l_exp, r_exp, location = exp(left_exp(expr)), exp( right_exp(expr)), loc(expr) # noinspection PyUnresolvedReferences '1 + 2 - 3 * 7 / 4' return binary_exp.rules[oper(expr)](expr=expr, left_exp=l_exp, right_exp=r_exp, location=location, exp_type=exp_type)
def address_of(expr, symbol_table): instrs = symbol_table['__ expression __'](exp(expr), symbol_table) value = next(instrs) for instr in instrs: yield value value = instr if not isinstance(value, Loads): yield value
def range_designated_expr(start, tokens, symbol_table): constant_expression = symbol_table['__ constant_expression __'] end = error_if_not_value(tokens, TOKENS.ELLIPSIS) and NumericalDesignation( exp(constant_expression(tokens, symbol_table)) ) return error_if_not_value(tokens, TOKENS.RIGHT_BRACKET) and RangeDesignatedExpression( start, end, _expr_or_designated_expr(tokens, symbol_table), loc(end) )
def parse_range_designated_expr(desig_expr, default_values): first, last = designation(desig_expr) exhaust( imap( parse_designated_expr, imap(OffsetDesignatedExpression, xrange(first, last + 1), repeat(exp(desig_expr)), repeat(loc(desig_expr))), repeat(default_values)))
def range_designated_expr(start, tokens, symbol_table): constant_expression = symbol_table['__ constant_expression __'] end = error_if_not_value(tokens, TOKENS.ELLIPSIS) and NumericalDesignation( exp(constant_expression(tokens, symbol_table))) return error_if_not_value( tokens, TOKENS.RIGHT_BRACKET) and RangeDesignatedExpression( start, end, _expr_or_designated_expr(tokens, symbol_table), loc(end))
def parse_identifier_designated_expr(desig_expr, default_values): return parse_designated_expr( OffsetDesignatedExpression( offset(c_type(default_values), designation(desig_expr)), # get offset ... exp(desig_expr), loc(desig_expr)), default_values)
def update_composite_type_initializer(desig_expr, default_values): desig = designation(desig_expr) if desig > default_values: logger.warning('Excess elements in initializer ...') else: assert len(default_values[desig]) == 1 default_values[desig][0] = cast(exp(desig_expr), c_type(default_values[desig][0]))
def address_of(expr, symbol_table): instrs = symbol_table['__ expression __'](exp(expr), symbol_table) value = next(instrs) for instr in instrs: yield value value = instr if not isinstance(value, Loads): yield value
def parse_range_designated_expr(desig_expr, default_values): first, last = designation(desig_expr) exhaust( imap( parse_designated_expr, imap(OffsetDesignatedExpression, xrange(first, last + 1), repeat(exp(desig_expr)), repeat(loc(desig_expr))), repeat(default_values) ) )
def parse_identifier_designated_expr(desig_expr, default_values): return parse_designated_expr( OffsetDesignatedExpression( offset(c_type(default_values), designation(desig_expr)), # get offset ... exp(desig_expr), loc(desig_expr) ), default_values )
def case(tokens, symbol_table): location = loc(loc(consume(tokens))) constant_expression, statement = imap( symbol_table.__getitem__, ('__ constant_expression __', '__ statement __')) expr = constant_expression(tokens, symbol_table) _, _ = error_if_not_value(tokens, TOKENS.COLON), error_if_not_type( c_type(expr), IntegralType) switch_cases = symbol_table['__ SWITCH STATEMENT __'] switch_exp = symbol_table['__ SWITCH EXPRESSION __'] if c_type(expr) != c_type(switch_exp): raise ValueError( '{l} case exp type {g} differs from switch exp type {e}'.format( l=location, g=c_type(expr), e=c_type(switch_exp))) switch_cases[exp(expr)] = CaseStatement(expr, statement(tokens, symbol_table), location) yield switch_cases[exp(expr)]
def parse_designated_union_expr(desig_expr, default_values): # care must be taken when dealing with union initializer, they may only set a single expression ... ctype, desig, expr = c_type(default_values), designation(desig_expr), exp(desig_expr) if isinstance(expr, DesignatedExpression): parse_designated_expr(expr, default_values) elif isinstance(expr, Initializer): set_default_initializer(expr, default_values) else: default_values[0] = expr
def parse_default_offset_designated_expr(desig_expr, default_values): ctype, desig, expr = c_type(default_values), designation(desig_expr), exp(desig_expr) if isinstance(expr, DesignatedExpression) and error_if_not_type(ctype, (StructType, ArrayType)): parse_designated_expr(expr, default_values[desig]) elif isinstance(expr, Initializer): default_values = default_values[desig] if isinstance(ctype, (StructType, ArrayType)) else default_values set_default_initializer(expr, default_values) else: update_default_value(desig_expr, default_values)
def offset_designated_expr(tokens, symbol_table): # '[' positive_integral (... positive_integral)? ']' constant_expression = error_if_not_value(tokens, TOKENS.LEFT_BRACKET) and symbol_table['__ constant_expression __'] designation = NumericalDesignation(exp(constant_expression(tokens, symbol_table))) if peek_or_terminal(tokens) == TOKENS.ELLIPSIS: return range_designated_expr(designation, tokens, symbol_table) return error_if_not_value(tokens, TOKENS.RIGHT_BRACKET) and OffsetDesignatedExpression( designation, _expr_or_designated_expr(tokens, symbol_table) )
def inc_dec(expr, symbol_table): assert not isinstance(c_type(expr), ArrayType) and isinstance( c_type(expr), IntegralType) value = rules(inc_dec)[type(expr)] if isinstance(c_type(expr), PointerType): value *= size_extended(c_type(c_type(expr))) return get_postfix_update(size(c_type(expr)))(all_but_last( symbol_table['__ expression __'](exp(expr), symbol_table), Loads, loc(expr)), value, loc(expr))
def inc_dec(value, expr, symbol_table): return symbol_table['__ expression __']( CompoundAssignmentExpression( exp(expr), TOKENS.PLUS_EQUAL, ConstantExpression( value, IntegerType(loc(expr), unsigned=unsigned(c_type(expr))), loc(expr)), c_type(expr)(loc(expr)), loc(expr)), symbol_table, )
def switch_statement(stmnt, symbol_table): _ = (not isinstance(c_type(exp(stmnt)), IntegralType)) and raise_error( '{l} Expected an integral type got {g}'.format(g=c_type(exp(stmnt)), l=loc(stmnt)) ) end_switch = Pass(loc(stmnt)) stmnt.stack = deepcopy(symbol_table['__ stack __']) # if switch inside loop, only update end_instruct, since continue jumps to start of loop break goes to end of switch def body(stmnt, symbol_table, end_switch): symbol_table = push(symbol_table) stack, statement = imap(symbol_table.__getitem__, ('__ stack __', '__ statement __')) symbol_table['__ break __'] = (end_switch, stack.stack_pointer) symbol_table['__ switch __'] = True allocation_table = [] # create an allocation table to update stack before jump in case of nested definitions switch_body_instrs = [] cases = {'default': Offset(end_switch, loc(stmnt))} for instr in statement(stmnt.statement, symbol_table): if isinstance(getattr(instr, 'case', None), CaseStatement): start = Pass(loc(instr)) allocation_table.append( chain( (start,), update_stack(stmnt.stack.stack_pointer, instr.case.stack.stack_pointer, loc(instr)), relative_jump(Offset(instr, loc(instr)), loc(instr)), ) ) cases[error_if_not_type(exp(exp(instr.case)), (int, long, str))] = Offset(start, loc(instr)) del instr.case switch_body_instrs.append(instr) max_switch_value = 2**(8*size_arrays_as_pointers(c_type(exp(stmnt)))) - 1 for instr in jump_table(loc(stmnt), cases, allocation_table, max_switch_value, switch_body_instrs): yield instr _ = pop(symbol_table) return chain( symbol_table['__ expression __'](exp(stmnt), symbol_table), body(stmnt, symbol_table, end_switch), (end_switch,) )
def parse_designated_union_expr(desig_expr, default_values): # care must be taken when dealing with union initializer, they may only set a single expression ... ctype, desig, expr = c_type(default_values), designation(desig_expr), exp( desig_expr) if isinstance(expr, DesignatedExpression): parse_designated_expr(expr, default_values) elif isinstance(expr, Initializer): set_default_initializer(expr, default_values) else: default_values[0] = expr
def inc_dec(value, expr, symbol_table): return symbol_table['__ expression __']( CompoundAssignmentExpression( exp(expr), TOKENS.PLUS_EQUAL, ConstantExpression(value, IntegerType(loc(expr), unsigned=unsigned(c_type(expr))), loc(expr)), c_type(expr)(loc(expr)), loc(expr) ), symbol_table, )
def inc_dec(expr, symbol_table): assert not isinstance(c_type(expr), ArrayType) and isinstance(c_type(expr), IntegralType) value = rules(inc_dec)[type(expr)] if isinstance(c_type(expr), PointerType): value *= size_extended(c_type(c_type(expr))) return get_postfix_update(size(c_type(expr)))( all_but_last(symbol_table['__ expression __'](exp(expr), symbol_table), Loads, loc(expr)), value, loc(expr) )
def for_statement(stmnt, symbol_table): start_of_loop, end_of_loop, upd_expression = imap(Pass, repeat(loc(stmnt), 3)) expression, statement, stack = imap( symbol_table.__getitem__, ('__ expression __', '__ statement __', '__ stack __') ) return chain( statement(stmnt.init_exp, symbol_table), # loop initialization. (start_of_loop,), # start of conditional # loop invariant. get_jump_false(size_arrays_as_pointers(c_type(exp(stmnt))))( expression(exp(stmnt), symbol_table), Offset(end_of_loop, loc(end_of_loop)), loc(stmnt) ), loop_body(stmnt.statement, symbol_table, upd_expression, end_of_loop), (upd_expression,), statement(stmnt.upd_exp, symbol_table), # loop update. relative_jump(Offset(start_of_loop, loc(start_of_loop)), loc(stmnt)), (end_of_loop,) )
def if_statement(stmnt, symbol_table): end_of_if, end_of_else = Pass(loc(stmnt)), Pass(loc(stmnt)) expression, statement = imap(symbol_table.__getitem__, ('__ expression __', '__ statement __')) for instr in chain( get_jump_false(size_arrays_as_pointers(c_type(exp(stmnt))))( expression(exp(stmnt), symbol_table), Offset(end_of_if, loc(end_of_if)), loc(end_of_if) ), statement(stmnt.statement, symbol_table) ): yield instr else_stmnt = stmnt.else_statement.statement if else_stmnt: for instr in chain( relative_jump(Offset(end_of_else, loc(end_of_else)), loc(stmnt)), (end_of_if,), statement(else_stmnt, symbol_table), (end_of_else,), ): yield instr else: yield end_of_if
def parse_default_offset_designated_expr(desig_expr, default_values): ctype, desig, expr = c_type(default_values), designation(desig_expr), exp( desig_expr) if isinstance(expr, DesignatedExpression) and error_if_not_type( ctype, (StructType, ArrayType)): parse_designated_expr(expr, default_values[desig]) elif isinstance(expr, Initializer): default_values = default_values[desig] if isinstance( ctype, (StructType, ArrayType)) else default_values set_default_initializer(expr, default_values) else: update_default_value(desig_expr, default_values)
def if_statement(stmnt, symbol_table): end_of_if, end_of_else = Pass(loc(stmnt)), Pass(loc(stmnt)) expression, statement = imap(symbol_table.__getitem__, ('__ expression __', '__ statement __')) for instr in chain( get_jump_false(size_arrays_as_pointers(c_type(exp(stmnt))))( expression(exp(stmnt), symbol_table), Offset(end_of_if, loc(end_of_if)), loc(end_of_if)), statement(stmnt.statement, symbol_table)): yield instr else_stmnt = stmnt.else_statement.statement if else_stmnt: for instr in chain( relative_jump(Offset(end_of_else, loc(end_of_else)), loc(stmnt)), (end_of_if, ), statement(else_stmnt, symbol_table), (end_of_else, ), ): yield instr else: yield end_of_if
def return_statement(stmnt, symbol_table): # TODO: check if we can omit the setting the return value if if it is immediately removed ... return_type = c_type(c_type(symbol_table['__ CURRENT FUNCTION __'])) assert not isinstance(c_type(return_type), ArrayType) if isinstance(return_type, VoidType) or not exp(stmnt): # just return if void type or expr is empty or size of expression is zero. return return_instrs(loc(stmnt)) return chain( cast(symbol_table['__ expression __'](exp(stmnt), symbol_table), c_type(exp(stmnt)), return_type, loc(stmnt)), set_instr( load( add(load_base_stack_pointer(loc(stmnt)), push(size(void_pointer_type), loc(stmnt)), loc(stmnt)), size(void_pointer_type), loc(stmnt) ), size(return_type), loc(stmnt) ), # TODO: see if we can remove the following instr, since pop_frame will reset the base and stack pointers # allocate(-size(return_type), loc(stmnt)), # Set leaves the value on the stack return_instrs(loc(stmnt)) )
def update_default_value(desig_expr, default_values): ctype, desig, expr = c_type(default_values), designation(desig_expr), exp(desig_expr) if desig >= len(default_values): logger.warning( '{0} Excess element {1} {2} in initializer, it will be ignored ... '.format( loc(desig_expr), desig, expr )) else: _ = (not safe_type_coercion(c_type(expr), c_type(default_values[desig]))) and raise_error( '{l} Unable to coerce from {f} to {t}'.format(l=loc(expr), f=c_type(expr), t=c_type(default_values[desig])) ) update_func = update_composite_type_initializer \ if isinstance(ctype, (StructType, ArrayType)) else update_scalar_type_initializer update_func(desig_expr, default_values)
def offset_designated_expr( tokens, symbol_table): # '[' positive_integral (... positive_integral)? ']' constant_expression = error_if_not_value( tokens, TOKENS.LEFT_BRACKET) and symbol_table['__ constant_expression __'] designation = NumericalDesignation( exp(constant_expression(tokens, symbol_table))) if peek_or_terminal(tokens) == TOKENS.ELLIPSIS: return range_designated_expr(designation, tokens, symbol_table) return error_if_not_value( tokens, TOKENS.RIGHT_BRACKET) and OffsetDesignatedExpression( designation, _expr_or_designated_expr(tokens, symbol_table))
def init_declarator(tokens, symbol_table, base_type=CType(''), storage_class=None): # : declarator ('=' assignment_expression or initializer)? decl = set_core_type(symbol_table['__ declarator __'](tokens, symbol_table), base_type) if peek_or_terminal(tokens) == TOKENS.EQUAL and consume(tokens): decl = Definition(name(decl), c_type(decl), EmptyExpression(c_type(decl)), loc(decl), storage_class) symbol_table[name(decl)] = decl # we have to add it to the symbol table for things like `int a = a;` expr = initializer_or_assignment_expression(tokens, symbol_table) # if declaration is an array type and the expression is of string_type then convert to initializer for parsing if isinstance(c_type(decl), ArrayType) and isinstance(c_type(expr), StringType): expr = Initializer( enumerate(exp(expr)), ArrayType(c_type(c_type(expr)), len(c_type(expr)), loc(expr)), loc(expr) ) decl.initialization = parse_initializer(expr, decl) if isinstance(expr, Initializer) else expr else: symbol_table[name(decl)] = decl = Declaration(name(decl), c_type(decl), loc(decl)) return decl
def cast_exp(expr): if c_type(expr) == c_type(exp(expr)): return exp(expr) if isinstance(exp(expr), ConstantExpression) and not isinstance(c_type(exp(expr)), ArrayType): to_type = c_type(expr) expr = exp(expr) location = loc(expr) if isinstance(expr, EmptyExpression): return EmptyExpression(to_type, loc(expr)) if isinstance(to_type, IntegralType): return ConstantExpression(int(exp(expr)), to_type(location), location) if isinstance(to_type, FloatType): return ConstantExpression(float(exp(expr)), to_type(location), location) return expr
def update_default_value(desig_expr, default_values): ctype, desig, expr = c_type(default_values), designation(desig_expr), exp( desig_expr) if desig >= len(default_values): logger.warning( '{0} Excess element {1} {2} in initializer, it will be ignored ... ' .format(loc(desig_expr), desig, expr)) else: _ = (not safe_type_coercion(c_type(expr), c_type( default_values[desig]))) and raise_error( '{l} Unable to coerce from {f} to {t}'.format( l=loc(expr), f=c_type(expr), t=c_type(default_values[desig]))) update_func = update_composite_type_initializer \ if isinstance(ctype, (StructType, ArrayType)) else update_scalar_type_initializer update_func(desig_expr, default_values)
def exclamation_operator(expr, symbol_table): if not isinstance(c_type(exp(expr)), NumericType): raise ValueError('{l} exclamation operator only supports numeric types got {g}'.format( l=loc(expr), g=c_type(exp(expr)) )) assert not isinstance(c_type(exp(expr)), ArrayType) expression = symbol_table['__ expression __'] return get_compare(size_arrays_as_pointers(c_type(exp(expr))))( expression(exp(expr), symbol_table), expression(ConstantExpression(0, c_type(exp(expr))(loc(expr)), loc(expr),), symbol_table), loc(expr), (load_zero_flag(loc(expr)),) )
def cast_exp(expr): if c_type(expr) == c_type(exp(expr)): return exp(expr) if isinstance(exp(expr), ConstantExpression) and not isinstance( c_type(exp(expr)), ArrayType): to_type = c_type(expr) expr = exp(expr) location = loc(expr) if isinstance(expr, EmptyExpression): return EmptyExpression(to_type, loc(expr)) if isinstance(to_type, IntegralType): return ConstantExpression(int(exp(expr)), to_type(location), location) if isinstance(to_type, FloatType): return ConstantExpression(float(exp(expr)), to_type(location), location) return expr
def parse_enum_members(tokens, symbol_table): constant_expression = symbol_table['__ constant_expression __'] location, members, current_value = loc(consume(tokens)), OrderedDict(), 0 while peek(tokens, TOKENS.RIGHT_BRACE) != TOKENS.RIGHT_BRACE: ident = error_if_not_type(consume(tokens, ''), IDENTIFIER) value = ConstantExpression(current_value, IntegerType(location), location) if peek_or_terminal(tokens) == TOKENS.EQUAL and consume(tokens): value = constant_expression(tokens, symbol_table) _ = error_if_not_type(c_type(value), IntegerType) current_value = error_if_not_type(exp(value), (int, long)) symbol_table[ident] = value # Add value to symbol_table members[ident] = Definition(ident, c_type(value), value, location) _ = peek_or_terminal(tokens) == TOKENS.COMMA and consume(tokens) _ = error_if_not_value(tokens, TOKENS.RIGHT_BRACE) return members
def initializer_desig_exprs(initializer, default_values): previous_desig_offset_mag = -1 for expr_or_desig_expr in initializer.itervalues(): if not isinstance(expr_or_desig_expr, DesignatedExpression): # assign default designation if none present ... expr_or_desig_expr = DefaultOffsetDesignationExpression( previous_desig_offset_mag + 1, # use previous designation ... expr_or_desig_expr, loc(expr_or_desig_expr) ) elif isinstance(expr_or_desig_expr, IdentifierDesignatedExpression): # if designation is an identifier expr_or_desig_expr = OffsetDesignatedExpression( offset(c_type(default_values), designation(expr_or_desig_expr)), # get offset ... exp(expr_or_desig_expr), loc(expr_or_desig_expr) ) expand_defaults(expr_or_desig_expr, default_values) # expand defaults for incomplete array types yield expr_or_desig_expr previous_desig_offset_mag = max_designation_mag(expr_or_desig_expr) # record designation in case we need new 1
def parse_enum_members(tokens, symbol_table): constant_expression = symbol_table['__ constant_expression __'] location, members, current_value = loc(consume(tokens)), OrderedDict(), 0 while peek(tokens, TOKENS.RIGHT_BRACE) != TOKENS.RIGHT_BRACE: ident = error_if_not_type(consume(tokens, ''), IDENTIFIER) value = ConstantExpression(current_value, IntegerType(location), location) if peek_or_terminal(tokens) == TOKENS.EQUAL and consume(tokens): value = constant_expression(tokens, symbol_table) _ = error_if_not_type(c_type(value), IntegerType) current_value = error_if_not_type(exp(value), (int, long)) symbol_table[ident] = value # Add value to symbol_table members[ident] = Definition(ident, c_type(value), value, location) _ = peek_or_terminal(tokens) == TOKENS.COMMA and consume(tokens) _ = error_if_not_value(tokens, TOKENS.RIGHT_BRACE) return members
def exclamation_operator(expr, symbol_table): if not isinstance(c_type(exp(expr)), NumericType): raise ValueError( '{l} exclamation operator only supports numeric types got {g}'. format(l=loc(expr), g=c_type(exp(expr)))) assert not isinstance(c_type(exp(expr)), ArrayType) expression = symbol_table['__ expression __'] return get_compare(size_arrays_as_pointers(c_type(exp(expr))))( expression(exp(expr), symbol_table), expression( ConstantExpression( 0, c_type(exp(expr))(loc(expr)), loc(expr), ), symbol_table), loc(expr), (load_zero_flag(loc(expr)), ))
def initializer_desig_exprs(initializer, default_values): previous_desig_offset_mag = -1 for expr_or_desig_expr in initializer.itervalues(): if not isinstance(expr_or_desig_expr, DesignatedExpression ): # assign default designation if none present ... expr_or_desig_expr = DefaultOffsetDesignationExpression( previous_desig_offset_mag + 1, # use previous designation ... expr_or_desig_expr, loc(expr_or_desig_expr)) elif isinstance(expr_or_desig_expr, IdentifierDesignatedExpression ): # if designation is an identifier expr_or_desig_expr = OffsetDesignatedExpression( offset(c_type(default_values), designation(expr_or_desig_expr)), # get offset ... exp(expr_or_desig_expr), loc(expr_or_desig_expr)) expand_defaults( expr_or_desig_expr, default_values) # expand defaults for incomplete array types yield expr_or_desig_expr previous_desig_offset_mag = max_designation_mag( expr_or_desig_expr) # record designation in case we need new 1
def body(stmnt, symbol_table, end_switch): symbol_table = push(symbol_table) stack, statement = imap(symbol_table.__getitem__, ('__ stack __', '__ statement __')) symbol_table['__ break __'] = (end_switch, stack.stack_pointer) symbol_table['__ switch __'] = True allocation_table = [ ] # create an allocation table to update stack before jump in case of nested definitions switch_body_instrs = [] cases = {'default': Offset(end_switch, loc(stmnt))} for instr in statement(stmnt.statement, symbol_table): if isinstance(getattr(instr, 'case', None), CaseStatement): start = Pass(loc(instr)) allocation_table.append( chain( (start, ), update_stack(stmnt.stack.stack_pointer, instr.case.stack.stack_pointer, loc(instr)), relative_jump(Offset(instr, loc(instr)), loc(instr)), )) cases[error_if_not_type(exp(exp(instr.case)), (int, long, str))] = Offset( start, loc(instr)) del instr.case switch_body_instrs.append(instr) max_switch_value = 2**(8 * size_arrays_as_pointers(c_type(exp(stmnt)))) - 1 for instr in jump_table(loc(stmnt), cases, allocation_table, max_switch_value, switch_body_instrs): yield instr _ = pop(symbol_table)
def cast_expression(expr, symbol_table): return cast(symbol_table['__ expression __'](exp(expr), symbol_table), c_type(exp(expr)), c_type(expr), loc(expr))
def assert_base_element(self, element): machine_word_type = word_type_factories[get_word_type_name(c_type(element))] self.assertEqual(base_element(self.cpu, self.mem, machine_word_type), exp(element))