예제 #1
0
def plug_arglist(func_def, arglist, caller_env, callee_env):

    pos_parmlist = func_def['pos_parmlist']
    pos_arglist = arglist.args
    if len(pos_parmlist) < len(pos_arglist):
        raise EvalError('Unmatched Function Positional Parameters', 
                get_topenv().get('$INPUT_LINES').get_content_around_pos(arglist.pos))

    kw_parmlist = func_def['kw_parmlist']
    kw_arglist = {}
    for kwarg in arglist.kwargs:
        kw_arglist[kwarg.parm_name.name] = kwarg.value.eval(caller_env)

    if not set.issubset(set(kw_arglist.keys()), set(kw_parmlist.keys())):
        raise EvalError('Unmatched Function Keyword Parameters',
                get_topenv().get('$INPUT_LINES').get_content_around_pos(arglist.pos))

    # plug positional arguments
    for ii in range(len(pos_parmlist)):
        value = pos_arglist[ii].eval(caller_env) if ii < len(pos_arglist) else None
        callee_env.set(pos_parmlist[ii], value)

    # plug keyword arguments
    for key in kw_parmlist.keys():
        value = kw_arglist[key] if key in kw_arglist.keys() else kw_parmlist[key]
        callee_env.set(key, value)
예제 #2
0
 def eval(self, env):
     var = self.collection.eval(env)
     if type(var) != list:
         raise EvalError('Can Only Slice a List: ' + str(var),
                 get_topenv().get('$INPUT_LINES').get_content_around_pos(self.pos))
     idxlist = self.idxlist.eval(env)
     try: 
         return var[idxlist]
     except IndexError:
         raise EvalError('List Index Out of Range',
                 get_topenv().get('$INPUT_LINES').get_content_around_pos(self.pos))
예제 #3
0
def parse_idxlist(tokenlist):
    'Parse the idxlist for array like variable'
    parsed = PT_Node(PN_IDXLIST)
    tokenlist.match(EPW_OP_L_BRACKET)
    # The start of the index
    if tokenlist.get().tag != EPW_OP_COLON:
        parsed.append(parse_expression(tokenlist))
    else:
        if tokenlist.get().tag != EPW_OP_COLON:
            raise ParseError('Incorrect index list format',
                    get_topenv().get('$INPUT_LINES').get_content_around_pos(tokenlist.get().pos))
        parsed.append(PT_Node(PN_NONE))
    # The optional end of the index
    if tokenlist.get().tag == EPW_OP_COLON:
        tokenlist.match(EPW_OP_COLON)
        if tokenlist.get().tag not in [EPW_OP_COLON, EPW_OP_R_BRACKET]:
            parsed.append(parse_expression(tokenlist))
        else:
            parsed.append(PT_Node(PN_NONE))
    # The optional step of the index
    if tokenlist.get().tag == EPW_OP_COLON:
        tokenlist.match(EPW_OP_COLON)
        if tokenlist.get().tag != EPW_OP_R_BRACKET:
            parsed.append(parse_expression(tokenlist))
        else:
            parsed.append(PT_Node(PN_NONE))
    tokenlist.match(EPW_OP_R_BRACKET)
    return parsed
예제 #4
0
def try_builtin_func(func_node, caller_env):

    func = func_node.func

    # if not a builtin func, we do not check
    name = func.name
    if name not in builtin_func_names:
        return (0, 0)

    else:
        nargs = len(func_node.arglist.args)
        range = builtin_func_def[name][0]
        if nargs < range[0] or nargs > range[1]:
            raise EvalError('Incorrect Parameters for Builtin Function', name)

    topenv = get_topenv()
    if name == 'debug':
        topenv.set('$DEBUG', 1 - topenv.get('$DEBUG'))
        return (1, None)

    elif name == 'list':
        if len(func_node.arglist.args) == 0:
            return (1, [])
        else:
            return (1, [0] * func_node.arglist.args[0].eval(caller_env))
예제 #5
0
def try_builtin_func(func_node, caller_env):

    func = func_node.func

    # if not a builtin func, we do not check
    name = func.name
    if name not in builtin_func_names:
        return (0, 0)

    else:
        nargs = len(func_node.arglist.args)
        range = builtin_func_def[name][0]
        if nargs < range[0] or nargs > range[1]:
            raise EvalError('Incorrect Parameters for Builtin Function', 
                            name)

    topenv = get_topenv()
    if name == 'debug':
        topenv.set('$DEBUG',  1-topenv.get('$DEBUG'))
        return (1, None)

    elif name == 'list':
        if len(func_node.arglist.args) == 0:
            return (1, [])
        else:
            return (1, [0] * func_node.arglist.args[0].eval(caller_env))
예제 #6
0
 def __init__(self):
     self.lex = Lexer()
     self.compiler = Compiler()
     self.vm = VM()
     for token_type in specs.token_type_list:
         self.lex.add_token_type(token_type)
     self.topenv = get_topenv()
     self.topenv.update(specs.SETTINGS)
예제 #7
0
 def match(self, tag_to_match):
     cur_token = self.get()
     if cur_token.tag == tag_to_match:
         self.pos += 1
     else:
         raise ParseError('Expected: ' + tag_to_match, 
                 get_topenv().get('$INPUT_LINES').get_content_around_pos(cur_token.pos))
     return cur_token
예제 #8
0
 def __init__(self):
     self.lex = Lexer()
     self.compiler = Compiler()
     self.vm = VM()
     for token_type in specs.token_type_list:
         self.lex.add_token_type(token_type)
     self.topenv = get_topenv()
     self.topenv.update(specs.SETTINGS)
예제 #9
0
def parse_simple_stmt(tokenlist):
    'A simple_stmt is a SINGLE stmt'
    token = tokenlist.get()
    if token.tag == EPW_KW_PRINT:
        parsed = parse_print_stmt(tokenlist)
    elif token.tag == EPW_KW_CONTINUE:
        tokenlist.match(EPW_KW_CONTINUE)
        parsed = PT_Node(PN_CONTINUE)
    elif token.tag == EPW_KW_BREAK:
        tokenlist.match(EPW_KW_BREAK)
        parsed = PT_Node(PN_BREAK)
    elif token.tag == EPW_KW_RETURN:
        tokenlist.match(EPW_KW_RETURN)
        # This parsing may not be optimal though it may works.
        parsed = PT_Node(PN_RETURN)
        if tokenlist.get().tag not in [EPW_OP_EOL, EPW_OP_SEMICOLON, EPW_OP_R_PAREN]:
            parsed.append(parse_r_expression(tokenlist))
    elif token.tag in [EPW_INT, EPW_FLOAT, EPW_STR]:
        parsed = parse_r_expression(tokenlist)
    elif token.tag == EPW_OP_SEMICOLON:
        parsed = parse_empty_stmt(tokenlist)
    elif is_unaryop(token):
        # a leading +/-/not, it can only be an expression 
        parsed = parse_r_expression(tokenlist)

    elif token.tag == EPW_ID:
        # Both ID, slice all start with an ID.
        # If the next token is a "=", it is an assignment with an ID.
        # If it is not, we need to do a regular expression match to 
        # find out whether it is a assignment to a slice.
        # A slice can be either a simple ID with [], ID[], or
        # a function call with [], f()[]

        if tokenlist.get(1).tag == EPW_OP_ASSIGN: # simple case of ID assignment
            parsed = parse_assign_stmt(tokenlist)

        else: # complicate case for possible slice assignment
            rest = tokenlist.get_rest_line()
            # Try to see if we have any function call or slices
            matched = regex_func_slice_mix_assign.match(rest)
            if matched:
                mstring = matched.group(0)
                if mstring[-3] == EPW_OP_R_PAREN:
                    raise ParseError('Cannot Assign to a Function Call', 
                            get_topenv().get('$INPUT_LINES').get_content_around_pos(tokenlist.get().pos))
                parsed = parse_ID(tokenlist)
                for c in mstring:
                    if c == EPW_OP_L_BRACKET:
                        parsed = parse_brackets(tokenlist, parsed)
                    elif c == EPW_OP_L_PAREN:
                        parsed = parse_parenthesis(tokenlist, parsed)
                parsed = parse_assign_stmt(tokenlist, parsed)
            else:
                parsed = parse_r_expression(tokenlist)

    else:
        tokenlist.match('token for a simple_stmt')
    return parsed
예제 #10
0
 def eval(self, env):
     ret = None
     top_env = get_topenv()
     for node in self.node_list:
         ret = node.eval(env)
         # Set value for magic variable
         if ret is not None:
             top_env.set('_', ret)
     return ret
예제 #11
0
 def eval(self, env):
     # Function can only be defined at the Top Level
     if env != get_topenv():
         raise EvalError('Function Definition Can Only Be at Top Level',
                 get_topenv().get('$INPUT_LINES').get_content_around_pos(self.pos))
     # Process any parameter list
     if self.parmlist:
         pos_parmlist = []
         for arg in self.parmlist.args:
             pos_parmlist.append(arg.name)
         kw_parmlist = {}
         for kwarg in self.parmlist.kwargs:
             kw_parmlist[kwarg.parm_name.name] = kwarg.value.eval(env)
     # Create the function definition and store in the top level 
     func_def = {'body': self.body, 
                 'pos_parmlist': pos_parmlist, 'kw_parmlist': kw_parmlist}
     env.set(self.func.name, func_def)
     return func_def
예제 #12
0
 def match(self, tag_to_match):
     cur_token = self.get()
     if cur_token.tag == tag_to_match:
         self.pos += 1
     else:
         raise ParseError(
             'Expected: ' + tag_to_match,
             get_topenv().get('$INPUT_LINES').get_content_around_pos(
                 cur_token.pos))
     return cur_token
예제 #13
0
 def eval(self, env):
     if self.op == '+':
         return self.operand.eval(env)
     elif self.op == '-':
         return -self.operand.eval(env)
     elif self.op == 'not':
         return 1 if not self.operand.eval(env) else 0
     else:
         raise EvalError('Unrecognized Unary Operator: ' + self.op,
                 get_topenv().get('$INPUT_LINES').get_content_around_pos(self.pos))
예제 #14
0
    def eval(self, env):
        try:
            # TODO: Still need to work on coerce
            if self.op == '+':
                return self.l.eval(env) + self.r.eval(env)
            elif self.op == '-':
                return self.l.eval(env) - self.r.eval(env)
            elif self.op == '*':
                return self.l.eval(env) * self.r.eval(env)
            elif self.op == '/':
                return self.l.eval(env) / self.r.eval(env)
            elif self.op == '%':
                return self.l.eval(env) % self.r.eval(env)
            elif self.op == '>':
                return self.l.eval(env) > self.r.eval(env)
            elif self.op == '<':
                return self.l.eval(env) < self.r.eval(env)
            elif self.op == '>=':
                return 1 if self.l.eval(env) >= self.r.eval(env) else 0
            elif self.op == '<=':
                return 1 if self.l.eval(env) <= self.r.eval(env) else 0
            elif self.op == '==':
                return 1 if self.l.eval(env) == self.r.eval(env) else 0
            elif self.op == '!=':
                return 1 if self.l.eval(env) != self.r.eval(env) else 0
            elif self.op == 'and':
                return 1 if self.l.eval(env) and self.r.eval(env) else 0
            elif self.op == 'or':
                return 1 if self.l.eval(env) or self.r.eval(env) else 0
            elif self.op == 'xor':
                return 1 if bool(self.l.eval(env)) != bool(self.r.eval(env)) else 0

            else:
                raise EvalError('Unrecognized Binary Operator: ' + self.op,
                        get_topenv().get('$INPUT_LINES').get_content_around_pos(self.pos))

        except TypeError as e:
            raise EvalError('Type Mismatch: ' + self.op,
                    get_topenv().get('$INPUT_LINES').get_content_around_pos(self.pos))
예제 #15
0
    def eval(self, caller_env):
        # Get the top env
        topenv = get_topenv()

        func = self.func
        # If the function call is a simple ID() form, we check whether it 
        # is a builtin function.
        # or get its definition from topenv.
        # This is not ideal, but since the language does not allow assign
        # another variable name to a builtin function. So it may work for
        # now.
        if repr(func).find('Variable(') == 0:
            # Check and run if its a builtin func
            flag, ret = try_builtin_func(self, caller_env)
            if flag: return ret

            # Otherwise, Get the func definition from top level
            name = func.name
            if topenv.has(name):
                func_def = get_topenv().get(name)
            else:
                raise EvalError('Undefined Function: ' + name,
                        get_topenv().get('$INPUT_LINES').get_content_around_pos(self.pos))
        else:
            func_def = func.eval(caller_env)

        # Plug the arglist
        callee_env = Environment(outer=caller_env)
        plug_arglist(func_def, self.arglist, caller_env, callee_env)
        
        # Evaluation
        try:
            ret = None
            ret = func_def['body'].eval(callee_env)
        except ReturnControl as e:
            if len(e.args) > 0:
                ret = e.args[0]

        return ret
예제 #16
0
 def eval(self, env):
     theEnv = env.find(self.name)
     if theEnv is None:
         raise EvalError('Variable Not Defined: ' + self.name, 
                 get_topenv().get('$INPUT_LINES').get_content_around_pos(self.pos))
     return theEnv.get(self.name)