예제 #1
0
파일: cvm.py 프로젝트: haldean/cvm
def run(args):
    if args.input_file:
        with open(args.input_file, "r") as input_file:
            source = input_file.read()
    else:
        import sys

        source = sys.stdin.read()

    if args.assemble:
        with open(args.output, "w") as binout:
            write_binary(parse_instructions(source), binout)
    else:
        tree = parse(preprocess(source))
        if args.print_ast:
            print_tree(tree)
        if not tree:
            return

        instructions = link(*translate(tree))
        if args.print_assembly:
            print_instructions(instructions)

        with open(args.output, "w") as binout:
            write_binary(instructions, binout)
예제 #2
0
파일: cvm.py 프로젝트: haldean/cvm
def run(args):
    if args.input_file:
        with open(args.input_file, 'r') as input_file:
            source = input_file.read()
    else:
        import sys
        source = sys.stdin.read()

    if args.assemble:
        with open(args.output, 'w') as binout:
            write_binary(parse_instructions(source), binout)
    else:
        tree = parse(preprocess(source))
        if args.print_ast:
            print_tree(tree)
        if not tree:
            return

        instructions = link(*translate(tree))
        if args.print_assembly:
            print_instructions(instructions)

        with open(args.output, 'w') as binout:
            write_binary(instructions, binout)
예제 #3
0
파일: translate.py 프로젝트: haldean/cvm
def translate_statement(ftree, glob, funcs):
  '''
  TODO:

  BREAK
  GOTO
  '''
  # Assignment
  if ftree[0] == '=':
    rhs = translate_statement(ftree[2], glob, funcs)
    return rhs + [('store', ftree[1])]

  # Variable access
  if ftree[1] == 'var':
    return [('load', ftree)]

  # Call stack-related
  if ftree[0] == 'call':
    # Calls to asm() skip translation and go straight to instruction parser.
    if ftree[1][0] == 'asm':
      return parse_instructions(ftree[2][0][0])
    func = funcs[ftree[1][0]]
    if len(func.args) != len(ftree[2]):
      raise Exception('Not enough arguments to function "%s"' % ftree[1][0])

    arg_evals = []
    for arg in ftree[2]:
      arg_evals.extend(translate_statement(arg, glob, funcs))
    funcpair = (ftree[1][0], 'func')
    return arg_evals + [('ldconst', funcpair), ('call', funcpair)]

  if ftree[0] == 'return':
    if ftree[1]:
      return translate_statement(ftree[1], glob, funcs) + [('return',)]
    else:
      return [('return',)]

  # Unary operators
  if ftree[0] == '++':
    return translate_unop_expression('incr', ftree, glob, funcs)
  if ftree[0] == '--':
    return translate_unop_expression('decr', ftree, glob, funcs)
  if ftree[0] == '~':
    return translate_unop_expression('not', ftree, glob, funcs)
  if ftree[0] == '!':
    return translate_unop_expression('bnot', ftree, glob, funcs)

  # Binary operators
  if ftree[0] == '*' and len(ftree) == 3:
    return translate_binop_expression('mul', ftree, glob, funcs)
  if ftree[0] == '+':
    return translate_binop_expression('add', ftree, glob, funcs)
  if ftree[0] == '-':
    return translate_binop_expression('sub', ftree, glob, funcs)
  if ftree[0] == '/':
    return translate_binop_expression('div', ftree, glob, funcs)
  if ftree[0] == '%':
    return translate_binop_expression('mod', ftree, glob, funcs)

  if ftree[0] == '&' and len(ftree[0]) == 3:
    return translate_binop_expression('and', ftree, glob, funcs)
  if ftree[0] == '|':
    return translate_binop_expression('or', ftree, glob, funcs)
  if ftree[0] == '^':
    return translate_binop_expression('xor', ftree, glob, funcs)

  if ftree[0] == '<<':
    return translate_binop_expression('lsh', ftree, glob, funcs)
  if ftree[0] == '>>':
    return translate_binop_expression('rsh', ftree, glob, funcs)

  if ftree[0] == '&&':
    return translate_binop_expression('band', ftree, glob, funcs)
  if ftree[0] == '||':
    return translate_binop_expression('bor', ftree, glob, funcs)

  # Comparison operators
  if ftree[0] == '==':
    return translate_binop_expression('eq', ftree, glob, funcs)
  if ftree[0] == '>=':
    return translate_binop_expression('geq', ftree, glob, funcs)
  if ftree[0] == '<=':
    return translate_binop_expression('leq', ftree, glob, funcs)
  if ftree[0] == '>':
    return translate_binop_expression('gt', ftree, glob, funcs)
  if ftree[0] == '<':
    return translate_binop_expression('lt', ftree, glob, funcs)
  if ftree[0] == '!=':
    return translate_binop_expression('neq', ftree, glob, funcs)

  # Assignment operators
  if ftree[0] == '+=':
    return translate_assign_expression('add', ftree, glob, funcs)
  if ftree[0] == '-=':
    return translate_assign_expression('sub', ftree, glob, funcs)
  if ftree[0] == '*=':
    return translate_assign_expression('mul', ftree, glob, funcs)
  if ftree[0] == '/=':
    return translate_assign_expression('div', ftree, glob, funcs)
  if ftree[0] == '%=':
    return translate_assign_expression('mod', ftree, glob, funcs)

  if ftree[0] == '&=':
    return translate_assign_expression('and', ftree, glob, funcs)
  if ftree[0] == '|=':
    return translate_assign_expression('or', ftree, glob, funcs)
  if ftree[0] == '^=':
    return translate_assign_expression('xor', ftree, glob, funcs)
  if ftree[0] == '>>=':
    return translate_assign_expression('rsh', ftree, glob, funcs)
  if ftree[0] == '<<=':
    return translate_assign_expression('lsh', ftree, glob, funcs)

  # Dereferencing
  if ftree[0] == '->':
    pass
  if ftree[0] == '.':
    pass
  if ftree[0] == '&':
    return [('addr', ftree[1])]
  if ftree[0] == '*':
    return (
        translate_statement(ftree[1], glob, funcs) +
        [('load', ('result', 'reg'))])

  # Conditionals
  if ftree[0] == 'if':
    code_true, ignore = translate_compound(ftree[2], glob, funcs)
    code_false, ignore = translate_compound(ftree[3], glob, funcs)
    return (
        translate_statement(ftree[1], glob, funcs) +
        # Conditional Offset Zero JuMP -- 
        # relative jump if result register == 0
        [('ozjmp', len(code_true) + 2)] +
        code_true +
        [('ojmp', len(code_false))] +
        code_false)

  if ftree[0] == '?':
    code_true = translate_statement(ftree[2], glob, funcs)
    code_false = translate_statement(ftree[3], glob, funcs)
    return (
        translate_statement(ftree[1], glob, funcs) +
        # Conditional Offset Zero JuMP -- 
        # relative jump if result register == 0
        [('ozjmp', len(code_true) + 2)] +
        code_true +
        [('ojmp', len(code_false))] +
        code_false +
        [('nop',)])

  if ftree[0] == 'while':
    condition = translate_statement(ftree[1], glob, funcs)
    code_true, ignore = translate_compound(ftree[2], glob, funcs)
    return (
        condition +
        [('ozjmp', len(code_true) + 2)] +
        code_true +
        [('ojmp', -len(code_true) - len(condition) - 1), ('nop',)])

  if ftree[0] == 'do':
    condition = translate_statement(ftree[1], glob, funcs)
    code_true, ignore = translate_compound(ftree[2], glob, funcs)
    return (
        code_true +
        condition +
        [('ozjmp', 2),
         ('ojmp', -len(code_true) - len(condition) - 1),
         ('nop',)])

  if ftree[0] == 'for':
    body, ignore = translate_compound(ftree[4], glob, funcs)
    condition = translate_statement(ftree[2], glob, funcs)
    update = []
    if ftree[3]:
      update = translate_statement(ftree[3], glob, funcs)

    return (
        translate_statement(ftree[1], glob, funcs) +
        condition +
        [('ozjmp', len(body) + len(update) + 2)] +
        body + update +
        [('ojmp', -len(body) - len(update) - len(condition) - 1), ('nop',)])

  # Numeric constant
  if ('i' in ftree[1] or 'l' in ftree[1] or
      'f' in ftree[1] or 'd' in ftree[1] or
      'c' in ftree[1]):
    return [('ldconst', ftree[0])]

  print('Warning: statement tree %s could not be translated.' % (ftree,))
  return []