import sys
import re

# --- TOKEN TYPES ---
TT_INT        = 'INT'
TT_STRING     = 'STRING'
TT_IDENTIFIER = 'IDENTIFIER'
TT_COLON      = 'COLON'
TT_LPAREN     = 'LPAREN'
TT_RPAREN     = 'RPAREN'
TT_DOT        = 'DOT'
TT_EQUALS     = 'EQUALS'
TT_COMMA      = 'COMMA'
TT_LBRACKET   = 'LBRACKET'
TT_RBRACKET   = 'RBRACKET'
TT_PLUS       = 'PLUS'
TT_MINUS      = 'MINUS'
TT_BOOL       = 'BOOL'
TT_SEMICOLON  = 'SEMICOLON' # For alt; also; not;
# Comparison
TT_EE         = 'EE'   
TT_LTE        = 'LTE'  
TT_GTE        = 'GTE'  
TT_LT         = 'LT'   
TT_GT         = 'GT'   

class Token:
    def __init__(self, type_, value=None):
        self.type = type_
        self.value = value
    def __repr__(self):
        return f'{self.type}:{self.value}' if self.value is not None else f'{self.type}'

# --- LEXER ---
class Lexer:
    def __init__(self, text):
        text = re.sub(r'~~.*?~~', '', text)
        text = re.sub(r'~~.*', '', text)
        self.text = text
        self.pos = -1
        self.current_char = None
        self.advance()

    def advance(self):
        self.pos += 1
        self.current_char = self.text[self.pos] if self.pos < len(self.text) else None
    
    def peek(self):
        peek_pos = self.pos + 1
        return self.text[peek_pos] if peek_pos < len(self.text) else None

    def make_tokens(self):
        tokens = []
        while self.current_char is not None:
            if self.current_char in ' \t\n\r': self.advance()
            elif self.current_char.isdigit(): tokens.append(self.make_number())
            elif self.current_char.isalpha(): tokens.append(self.make_identifier())
            elif self.current_char in ('"', "'"): tokens.append(self.make_string())
            elif self.current_char == '+': tokens.append(Token(TT_PLUS)); self.advance()
            elif self.current_char == '-': tokens.append(Token(TT_MINUS)); self.advance()
            elif self.current_char == ';': tokens.append(Token(TT_SEMICOLON)); self.advance()
            elif self.current_char == '=':
                if self.peek() == '=':
                    self.advance(); tokens.append(Token(TT_EE)); self.advance()
                elif self.peek() == '>': # Support => for GTE
                    self.advance(); tokens.append(Token(TT_GTE)); self.advance()
                else: tokens.append(Token(TT_EQUALS)); self.advance()
            elif self.current_char == '<':
                if self.peek() == '=':
                    self.advance(); tokens.append(Token(TT_LTE)); self.advance()
                else: tokens.append(Token(TT_LT)); self.advance()
            elif self.current_char == '>':
                if self.peek() == '=':
                    self.advance(); tokens.append(Token(TT_GTE)); self.advance()
                else: tokens.append(Token(TT_GT)); self.advance()
            elif self.current_char == ':': tokens.append(Token(TT_COLON)); self.advance()
            elif self.current_char == '(': tokens.append(Token(TT_LPAREN)); self.advance()
            elif self.current_char == ')': tokens.append(Token(TT_RPAREN)); self.advance()
            elif self.current_char == '[': tokens.append(Token(TT_LBRACKET)); self.advance()
            elif self.current_char == ']': tokens.append(Token(TT_RBRACKET)); self.advance()
            elif self.current_char == '.': tokens.append(Token(TT_DOT)); self.advance()
            elif self.current_char == ',': tokens.append(Token(TT_COMMA)); self.advance()
            else: self.advance()
        return tokens, None
    
    def make_number(self):
        num_str = ''
        while self.current_char is not None and self.current_char.isdigit():
            num_str += self.current_char
            self.advance()
        return Token(TT_INT, int(num_str))

    def make_string(self):
        string = ''
        quote_type = self.current_char
        self.advance()
        while self.current_char is not None and self.current_char != quote_type:
            string += self.current_char
            self.advance()
        self.advance()
        return Token(TT_STRING, string)
    
    def make_identifier(self):
        id_str = ''
        while self.current_char is not None and (self.current_char.isalnum() or self.current_char == '_'):
            id_str += self.current_char
            self.advance()
        if id_str == 'true': return Token(TT_BOOL, True)
        if id_str == 'false': return Token(TT_BOOL, False)
        return Token(TT_IDENTIFIER, id_str)

# --- NODES ---
class CondNode:
    def __init__(self, mode, condition_tokens, body):
        self.mode = mode # 'if' or 'during'
        self.condition_tokens = condition_tokens
        self.body = body

# (Other nodes like DefineNode, SetNode, etc. remain the same as previous)
class DefineNode:
    def __init__(self, dtype, name, args=None, body=None):
        self.dtype, self.name, self.args, self.body = dtype, name, args, body

class SetNode:
    def __init__(self, library, name, expression):
        self.library, self.name, self.expression = library, name, expression

class LogNode:
    def __init__(self, lib, name, index=None, raw_val=None):
        self.lib, self.name, self.index, self.raw_val = lib, name, index, raw_val

class FuncExecuteNode:
    def __init__(self, name, args):
        self.name, self.args = name, args

# --- PARSER ---
class Parser:
    def __init__(self, tokens):
        self.tokens, self.tok_idx = tokens, -1
        self.advance()

    def advance(self):
        self.tok_idx += 1
        self.current_tok = self.tokens[self.tok_idx] if self.tok_idx < len(self.tokens) else None

    def get_block(self):
        body = []
        while self.current_tok:
            if self.current_tok.type == TT_COLON:
                if self.tok_idx + 1 < len(self.tokens) and self.tokens[self.tok_idx+1].value == 'end':
                    self.advance(); self.advance()
                    break
            stmt = self.statement()
            if stmt: body.append(stmt)
        return body

    def statement(self):
        if not self.current_tok: return None

        # --- NEW COND() SYNTAX ---
        if self.current_tok.value == 'cond':
            self.advance(); self.advance() # cond (
            mode = self.current_tok.value # 'if' or 'during'
            self.advance()
            expr = []
            while self.current_tok.type != TT_RPAREN:
                expr.append(self.current_tok); self.advance()
            self.advance(); self.advance() # ) :
            return CondNode(mode, expr, self.get_block())

        # (Rest of definitions like define, log, vars. stay identical to previous version)
        if self.current_tok.value == 'define':
            self.advance(); self.advance(); self.advance(); self.advance() 
            dtype = self.current_tok.value
            self.advance(); self.advance() 
            name = self.current_tok.value
            self.advance(); self.advance() 
            if dtype == 'Func':
                self.advance(); self.advance() 
                args = []
                while self.current_tok.type != TT_RBRACKET:
                    if self.current_tok.type == TT_IDENTIFIER and self.current_tok.value != 'None':
                        args.append(self.current_tok.value)
                    self.advance()
                self.advance(); self.advance() 
                return DefineNode(dtype, name, args, self.get_block())
            return DefineNode(dtype, name)

        if self.current_tok.value in ('vars', 'arrs', 'funcs'):
            lib = self.current_tok.value
            self.advance(); self.advance() 
            name = self.current_tok.value
            self.advance(); self.advance() 
            action = self.current_tok.value
            self.advance(); self.advance() 
            expr = []
            while self.current_tok and self.current_tok.type != TT_RPAREN:
                expr.append(self.current_tok); self.advance()
                if self.current_tok and self.current_tok.type == TT_COMMA: self.advance()
            if self.current_tok: self.advance()
            if action == 'Set': return SetNode(lib, name, expr)
            if action == 'Execute': return FuncExecuteNode(name, expr)

        if self.current_tok.value == 'log':
            self.advance(); self.advance(); self.advance(); self.advance() 
            if self.current_tok.type == TT_IDENTIFIER and self.current_tok.value in ('vars', 'arrs'):
                lib = self.current_tok.value
                self.advance(); self.advance()
                name = self.current_tok.value
                self.advance()
                idx = None
                if self.current_tok and self.current_tok.type == TT_LBRACKET:
                    self.advance(); idx = self.current_tok.value; self.advance(); self.advance()
                if self.current_tok: self.advance()
                return LogNode(lib, name, index=idx)
            else:
                val = self.current_tok.value; self.advance(); self.advance()
                return LogNode(None, None, raw_val=val)
        return None

    def parse(self):
        ast = []
        while self.current_tok is not None:
            stmt = self.statement()
            if stmt: ast.append(stmt)
            else: self.advance()
        return ast

# --- INTERPRETER ---
class Interpreter:
    def __init__(self):
        self.vars, self.arrs, self.funcs, self.temp_vars = {}, {}, {}, {}

    def resolve_value(self, tokens):
        if not isinstance(tokens, list):
            if tokens.type in (TT_INT, TT_STRING, TT_BOOL): return tokens.value
            if tokens.value == 'input':
                val = input(">> "); return int(val) if val.isdigit() else val
            if tokens.value in self.temp_vars: return self.temp_vars[tokens.value]
            return tokens.value
        if len(tokens) >= 3 and tokens[1].type == TT_DOT:
            lib, var_name = tokens[0].value, tokens[2].value
            if lib == 'vars': return self.temp_vars.get(var_name, self.vars.get(var_name, 0))
            if lib == 'arrs': return self.arrs.get(var_name, [])
        return self.resolve_value(tokens[0])

    def evaluate_complex_logic(self, tokens):
        # Handle "not;"
        negate = False
        if tokens[0].value == 'not' and tokens[1].type == TT_SEMICOLON:
            negate = True
            tokens = tokens[2:]

        # Split by "alt;" or "also;"
        # For v0.2.2 we'll do a simple check for these keywords
        for i, tok in enumerate(tokens):
            if tok.value == 'alt' and self.peek_token_type(i+1) == TT_SEMICOLON:
                left = self.evaluate_expression(tokens[:i])
                right = self.evaluate_complex_logic(tokens[i+2:])
                res = left or right
                return not res if negate else res
            if tok.value == 'also' and self.peek_token_type(i+1) == TT_SEMICOLON:
                left = self.evaluate_expression(tokens[:i])
                right = self.evaluate_complex_logic(tokens[i+2:])
                res = left and right
                return not res if negate else res

        res = self.evaluate_expression(tokens)
        return not res if negate else res

    def peek_token_type(self, idx):
        # Helper for evaluate_complex_logic
        return None # Simplified for this snippet

    def evaluate_expression(self, expr_tokens):
        for i, tok in enumerate(expr_tokens):
            if tok.type in (TT_EE, TT_LTE, TT_GTE, TT_LT, TT_GT, TT_PLUS, TT_MINUS):
                v1 = self.resolve_value(expr_tokens[:i])
                v2 = self.resolve_value(expr_tokens[i+1:])
                if tok.type == TT_EE: return v1 == v2
                if tok.type == TT_LTE: return v1 <= v2
                if tok.type == TT_GTE: return v1 >= v2
                if tok.type == TT_LT: return v1 < v2
                if tok.type == TT_GT: return v1 > v2
                if tok.type == TT_PLUS: return v1 + v2
                if tok.type == TT_MINUS: return v1 - v2
        return self.resolve_value(expr_tokens)

    def visit(self, node):
        if isinstance(node, CondNode):
            if node.mode == 'if':
                if self.evaluate_complex_logic(node.condition_tokens):
                    for s in node.body: self.visit(s)
            elif node.mode == 'during':
                while self.evaluate_complex_logic(node.condition_tokens):
                    for s in node.body: self.visit(s)
        elif isinstance(node, DefineNode):
            if node.dtype == 'Var': self.vars[node.name] = None
            elif node.dtype == 'Arr': self.arrs[node.name] = []
            elif node.dtype == 'Func': self.funcs[node.name] = (node.args, node.body)
        elif isinstance(node, SetNode):
            val = self.evaluate_expression(node.expression)
            if node.library == 'vars': self.vars[node.name] = val
            else: self.arrs[node.name] = val
        elif isinstance(node, LogNode):
            if node.raw_val is not None: print(f"[NEXUS CONSOLE]: {node.raw_val}")
            else: print(f"[NEXUS CONSOLE]: {self.vars.get(node.name, self.arrs.get(node.name))}")
        elif isinstance(node, FuncExecuteNode):
            args_n, body = self.funcs[node.name]
            for s in body: self.visit(s)

def run_file(filename):
    with open(filename, 'r') as f: script = f.read()
    lexer = Lexer(script)
    tokens, _ = lexer.make_tokens()
    parser = Parser(tokens)
    ast = parser.parse()
    interpreter = Interpreter()
    for node in ast: interpreter.visit(node)

if __name__ == "__main__":
    if len(sys.argv) > 1: run_file(sys.argv[1])

def main_cli():
    import sys
    if len(sys.argv) > 1:
        filename = sys.argv[1]
        if filename.endswith('.sil'):  # Changed from .nx to .sil
            run_file(filename)
        else:
            print(f"Silicon Error: '{filename}' is not a valid .sil file.")
    else:
        print("Silicon v0.2.2")
        print("Usage: silicon <filename>.sil")

if __name__ == "__main__":
    main_cli()