Skip to content

For Developers

Pranav Verma edited this page Nov 26, 2024 · 3 revisions

For Developers

This page provides technical documentation for developers who want to understand or contribute to Tidal's codebase.

Prerequirements

  • Rust (High).
  • Cargo Toolchain

Architecture Overview

Tidal is implemented in Rust and follows a traditional compiler/interpreter architecture:

  1. Lexer (lexer.rs): Converts source code into tokens
  2. Parser (parser.rs): Converts tokens into an Abstract Syntax Tree (AST)
  3. Interpreter (interpreter.rs): Executes the AST

Core Components

Lexer

  • Defined in lexer.rs
  • Implements token recognition for language constructs
  • Key token types include:
    • Keywords (var, novar, print, etc.)
    • Operators (+, -, *, /, etc.)
    • Literals (numbers, strings, booleans)
    • Identifiers
    • Delimiters

Parser

  • Defined in parser.rs
  • Creates AST nodes from token stream
  • Implements operator precedence and grammar rules
  • Maintains scope information
  • Key structures:
    • ASTNode enum: Represents all possible syntax constructs
    • Value enum: Represents runtime values
    • Parser struct: Main parsing logic

Interpreter

  • Defined in interpreter.rs
  • Executes AST nodes
  • Manages variable environment
  • Handles function calls and library imports
  • Implements type checking and runtime error handling

Error Handling

Errors are centralized in error.rs with the Error enum covering:

  • Syntax errors
  • Type errors
  • Runtime errors
  • IO errors
  • Library-related errors

Build

  • For Windows: cargo build --release
  • For Unix: cargo build --release --features unix

Libraries

Setup

Library Structure

use super::Library;
use crate::error::Error;
use crate::parser::Value;
use std::collections::HashMap;

pub struct MyLib {
    functions: HashMap<String, Box<dyn Fn(Vec<Value>) -> Result<Value, Error>>>,
    constants: HashMap<String, Value>,
}

impl Library for MyLib {
    fn get_function(&self, name: &str) -> Option<&Box<dyn Fn(Vec<Value>) -> Result<Value, Error>>> {
        self.functions.get(name)
    }

    fn get_constant(&self, name: &str) -> Option<&Value> {
        self.constants.get(name)
    }
}

impl MyLib {
    pub fn new() -> Self {
        let mut lib = MyLib {
            functions: HashMap::new(),
            constants: HashMap::new(),
        };
        lib.register_functions();
        lib.register_constants();
        lib
    }

    fn register_functions(&mut self) {
        self.functions.insert("example".to_string(), Box::new(|args| {
            Ok(Value::Null)
        }));
    }

    fn register_constants(&mut self) {
        self.constants.insert("CONSTANT".to_string(), Value::Number(42));
    }
}

Check out the Developers Wiki page for more information.

Contributing

  • Add your library to src/libs/mod.rs
  • Update Environment::new() in interpreter.rs
  • Create pull request with:
    • Library implementation
    • Documentation (In this Wiki Page).
    • Example usage
    • Test cases
  • Remember to follow Rust best practices and include proper error handling.

Brain Rot Mode Overview ☠️

The Brain Rot Mode is a Simple Replace Function at main.rs.

Details

  • Located in main.rs as preprocess_skibidi()
  • Uses HashMap for token replacement
  • Preserves whitespace and special characters
  • Maintains line numbers for error reporting