# DSC Language Specification v1.0 **Damn Simple C (DSC)** - A systems programming language for the DSA architecture --- ## Table of Contents 1. [Introduction](#introduction) 2. [Lexical Structure](#lexical-structure) 3. [Types](#types) 4. [Variables and Declarations](#variables-and-declarations) 5. [Classes](#classes) 6. [Functions](#functions) 7. [Expressions](#expressions) 8. [Statements](#statements) 9. [Control Flow](#control-flow) 10. [Memory Management](#memory-management) 11. [Generics](#generics) 12. [Modules and Imports](#modules-and-imports) 13. [Keywords](#keywords) 14. [Operators](#operators) 15. [Complete Example Programs](#complete-example-programs) 16. [Grammar Summary](#grammar-summary) 17. [Appendix A: Differences from Rust](#appendix-a-differences-from-rust) 18. [Appendix B: Standard Library Conventions](#appendix-b-standard-library-conventions) --- ## 1. Introduction DSC is a statically-typed systems programming language designed for the DSA (Damn Simple Architecture). It combines modern syntax with explicit memory management and direct assembly interoperability. ### Design Goals - **Explicit**: No hidden control flow or implicit conversions - **Simple**: Easy to understand what the compiler generates - **Safe**: Scope-based resource management via `defer` - **Interoperable**: Direct assembly library integration --- ## 2. Lexical Structure ### 2.1 Comments ```rust // Single-line comment /* Multi-line comment */ ``` ### 2.2 Identifiers Identifiers must start with a letter or underscore, followed by any number of letters, digits, or underscores. ```rust valid_identifier _private MyClass get_value_42 ``` ### 2.3 Reserved Keywords ``` as break class const continue defer else false field fn if impl include let loop mut priv pub return self static struct true void while ``` ### 2.4 Literals #### Integer Literals ```rust 42 // Decimal 0x2A // Hexadecimal 0b101010 // Binary 0o52 // Octal ``` #### String Literals ```rust "Hello, world!" "Escape sequences: \n \t \\ \"" ``` #### Boolean Literals ```rust true false ``` --- ## 3. Types ### 3.1 Primitive Types #### Integer Types ```rust i8 // Signed 8-bit integer i16 // Signed 16-bit integer i32 // Signed 32-bit integer i64 // Signed 64-bit integer u8 // Unsigned 8-bit integer u16 // Unsigned 16-bit integer u32 // Unsigned 32-bit integer u64 // Unsigned 64-bit integer ``` #### Boolean Type ```rust bool // true or false ``` #### String Type ```rust str // String literal type (pointer to null-terminated byte array) ``` #### Void Type ```rust void // Absence of a value (only valid as return type) ``` ### 3.2 Pointer Types Pointers are declared using the `&` prefix: ```rust &u32 // Pointer to u32 &bool // Pointer to bool &Point // Pointer to Point class ``` **Note**: Pointers in DSC are raw memory addresses (like C pointers), not Rust-style references with borrow checking. ### 3.3 Array Types ```rust [u32; 10] // Fixed-size array of 10 u32 values [bool; 256] // Fixed-size array of 256 bool values ``` ### 3.4 Generic Types ```rust Vec // Generic type with one type parameter Map // Generic type with multiple type parameters ``` --- ## 4. Variables and Declarations ### 4.1 Variable Declaration Variables are declared with `let` and are immutable by default: ```rust let x: u32 = 42; let name: str = "Alice"; let ptr: &u32 = &x; ``` ### 4.2 Mutable Variables Use `mut` to declare mutable variables: ```rust let mut count: u32 = 0; count = count + 1; ``` ### 4.3 Type Inference Type annotations can be omitted when the type can be inferred: ```rust let x = 42; // Inferred as u32 (default integer type) let name = "Bob"; // Inferred as str ``` --- ## 5. Classes Classes are DSC's primary means of encapsulation, combining data and behavior. ### 5.1 Class Definition ```rust class ClassName { // Class body } ``` ### 5.2 Fields Fields represent the data members of a class. They must be explicitly marked as `pub` or `priv`: ```rust class Point { pub field x: u32; pub field y: u32; priv field cached: bool; } ``` **Syntax**: `[pub|priv] field : ;` ### 5.3 Constants Constants are compile-time values associated with a class: ```rust class Math { pub const PI: u32 = 3; pub const E: u32 = 2; priv const INTERNAL_CONSTANT: u32 = 42; } ``` **Syntax**: `[pub|priv] const : = ;` **Usage**: `Math::PI` ### 5.4 Static Fields Static fields are global variables associated with a class: ```rust class Logger { pub static mut INSTANCE_COUNT: u32 = 0; priv static mut INTERNAL_STATE: u32 = 0; } ``` **Syntax**: `[pub|priv] static mut : = ;` **Usage**: ```rust Logger::INSTANCE_COUNT = Logger::INSTANCE_COUNT + 1; ``` **Note**: All static fields must be declared `mut` as they represent mutable global state. ### 5.5 Methods Methods are functions associated with a class. Instance methods take a `self` parameter: ```rust class Point { pub field x: u32; pub field y: u32; // Constructor (static method) pub fn new(x: u32, y: u32) -> Point { return Point { x: x, y: y }; } // Instance method pub fn get_x(self: &Point) -> u32 { return self.x; } // Mutable instance method pub fn set_x(self: &Point, value: u32) { self.x = value; } // Static method pub fn zero() -> Point { return Point { x: 0, y: 0 }; } } ``` **Method Syntax**: - Instance method: `[pub|priv] fn (self: &, ...) -> ` - Static method: `[pub|priv] fn (...) -> ` ### 5.6 Class Instantiation ```rust // Using constructor let p1: Point = Point::new(10, 20); // Using struct literal syntax let p2: Point = Point { x: 5, y: 15 }; ``` ### 5.7 Method Calls ```rust let p: Point = Point::new(10, 20); // Method call syntax (preferred) let x: u32 = p.get_x(); // Explicit syntax (equivalent) let x: u32 = Point::get_x(&p); // Static method call let origin: Point = Point::zero(); ``` ### 5.8 Field Access ```rust let p: Point = Point { x: 10, y: 20 }; // Read field let x: u32 = p.x; // Write field (if mutable) let mut p2: Point = Point { x: 0, y: 0 }; p2.x = 42; ``` ### 5.9 Complete Class Example ```rust class Vec { priv field data: &u32; priv field len: u32; priv field capacity: u32; pub const DEFAULT_CAPACITY: u32 = 16; pub static mut TOTAL_ALLOCATIONS: u32 = 0; pub fn new(capacity: u32) -> Vec { Vec::TOTAL_ALLOCATIONS = Vec::TOTAL_ALLOCATIONS + 1; return Vec { data: alloc::malloc(capacity * 4) as &u32, len: 0, capacity: capacity }; } pub fn with_default_capacity() -> Vec { return Vec::new(Vec::DEFAULT_CAPACITY); } pub fn push(self: &Vec, item: u32) { if self.len == self.capacity { self.grow(); } *(self.data + self.len) = item; self.len = self.len + 1; } pub fn get(self: &Vec, index: u32) -> u32 { return *(self.data + index); } priv fn grow(self: &Vec) { let new_capacity: u32 = self.capacity * 2; let new_data: &u32 = alloc::malloc(new_capacity * 4) as &u32; // Copy old data let mut i: u32 = 0; while i < self.len { *(new_data + i) = *(self.data + i); i = i + 1; } alloc::free(self.data as u32); self.data = new_data; self.capacity = new_capacity; } pub fn drop(self: &Vec) { alloc::free(self.data as u32); } } ``` --- ## 6. Functions ### 6.1 Function Declaration ```rust fn function_name(param1: Type1, param2: Type2) -> ReturnType { // Function body } ``` ### 6.2 Return Type Functions without a return value use `void` or omit the return type: ```rust fn print_message(msg: str) -> void { // No return value } // Equivalent fn print_message(msg: str) { // No return value } ``` ### 6.3 Return Statement ```rust fn add(a: u32, b: u32) -> u32 { return a + b; } ``` ### 6.4 Function Parameters ```rust fn process(value: u32, ptr: &u32, flag: bool) -> u32 { // ... } ``` --- ## 7. Expressions ### 7.1 Literals ```rust 42 // Integer literal 0xFF // Hex literal true // Boolean literal "hello" // String literal ``` ### 7.2 Binary Operations ```rust a + b // Addition a - b // Subtraction a * b // Multiplication a / b // Division a % b // Modulo ``` ### 7.3 Comparison Operations ```rust a == b // Equal a != b // Not equal a < b // Less than a > b // Greater than a <= b // Less than or equal a >= b // Greater than or equal ``` ### 7.4 Logical Operations ```rust a && b // Logical AND a || b // Logical OR !a // Logical NOT ``` ### 7.5 Bitwise Operations ```rust a & b // Bitwise AND a | b // Bitwise OR a ^ b // Bitwise XOR ~a // Bitwise NOT a << b // Left shift a >> b // Right shift ``` ### 7.6 Address-of and Dereference ```rust &x // Address-of (get pointer to x) *ptr // Dereference (read/write through pointer) ``` ### 7.7 Type Casting ```rust value as u32 // Cast value to u32 ptr as &u8 // Cast pointer type ``` ### 7.8 Field Access ```rust obj.field // Access field of object ptr.field // Access field through pointer (implicit dereference) ``` ### 7.9 Method Call ```rust obj.method(args) // Instance method call Class::method(args) // Static method call ``` ### 7.10 Array Indexing ```rust arr[index] // Access array element ``` --- ## 8. Statements ### 8.1 Expression Statement ```rust function_call(); x = y + 1; ``` ### 8.2 Variable Declaration ```rust let x: u32 = 42; let mut y: u32 = 0; ``` ### 8.3 Assignment ```rust x = 10; *ptr = 20; obj.field = 30; arr[0] = 40; ``` ### 8.4 Compound Assignment ```rust x += 5; // x = x + 5 x -= 3; // x = x - 3 x *= 2; // x = x * 2 x /= 4; // x = x / 4 ``` --- ## 9. Control Flow ### 9.1 If Statement ```rust if condition { // then block } if condition { // then block } else { // else block } if condition1 { // block 1 } else if condition2 { // block 2 } else { // block 3 } ``` ### 9.2 While Loop ```rust while condition { // loop body } ``` ### 9.3 Loop (Infinite Loop) ```rust loop { // infinite loop if should_exit { break; } } ``` ### 9.4 Break and Continue ```rust while condition { if skip_condition { continue; // Skip to next iteration } if exit_condition { break; // Exit loop } } ``` --- ## 10. Memory Management ### 10.1 Defer Statement The `defer` keyword schedules a statement to execute when the current scope exits. ```rust fn example() { let ptr: u32 = alloc::malloc(256); defer alloc::free(ptr); // Use ptr... if error { return; // defer runs here } // More work... } // defer runs here ``` ### 10.2 Defer Execution Rules 1. **Scope-based**: Defers execute when their enclosing scope exits 2. **LIFO order**: Multiple defers execute in reverse order of declaration 3. **All exit paths**: Defers run on return, break, continue, or natural scope end ```rust fn nested_defers() { let a: u32 = alloc::malloc(100); defer alloc::free(a); // Runs second if condition { let b: u32 = alloc::malloc(200); defer alloc::free(b); // Runs first (if in this scope) // ... work ... } // b's defer runs here // ... more work ... } // a's defer runs here ``` ### 10.3 Defer with Methods ```rust class Resource { priv field handle: u32; pub fn acquire() -> Resource { return Resource { handle: alloc::malloc(1024) }; } pub fn release(self: &Resource) { alloc::free(self.handle); } } fn use_resource() { let res: Resource = Resource::acquire(); defer res.release(); // Use resource... } // res.release() automatically called ``` --- ## 11. Generics ### 11.1 Generic Classes ```rust class Box { priv field value: T; pub fn new(value: T) -> Box { return Box { value: value }; } pub fn get(self: &Box) -> T { return self.value; } pub fn set(self: &Box, value: T) { self.value = value; } } ``` ### 11.2 Generic Usage ```rust let int_box: Box = Box::new(42); let str_box: Box = Box::new("hello"); let value: u32 = int_box.get(); ``` ### 11.3 Multiple Type Parameters ```rust class Pair { pub field first: T; pub field second: U; pub fn new(first: T, second: U) -> Pair { return Pair { first: first, second: second }; } } let p: Pair = Pair::new(42, "answer"); ``` ### 11.4 Generic Functions ```rust fn swap(a: &T, b: &T) { let temp: T = *a; *a = *b; *b = temp; } let mut x: u32 = 1; let mut y: u32 = 2; swap(&x, &y); ``` ### 11.5 Generic Constraints **Note**: DSC does not support trait bounds or where clauses. Generic types are instantiated via monomorphization without constraints. --- ## 12. Modules and Imports ### 12.1 Assembly Imports DSC can import assembly modules for low-level operations: ```rust include print: "./lib/io/print.dsa"; include alloc: "./lib/memory/alloc.dsa"; ``` **Syntax**: `include : "";` ### 12.2 Using Imported Functions ```rust print::println("Hello, world!"); let ptr: u32 = alloc::malloc(256); ``` --- ## 13. Keywords ### 13.1 Complete Keyword List | Keyword | Purpose | |---------|---------| | `as` | Type casting | | `break` | Exit loop | | `class` | Class definition | | `const` | Constant declaration | | `continue` | Next loop iteration | | `defer` | Defer statement execution | | `else` | Alternative branch | | `false` | Boolean literal | | `field` | Class field declaration | | `fn` | Function declaration | | `if` | Conditional statement | | `impl` | *Reserved for future use* | | `include` | Import assembly module | | `let` | Variable declaration | | `loop` | Infinite loop | | `mut` | Mutable binding | | `priv` | Private visibility | | `pub` | Public visibility | | `return` | Return from function | | `self` | Instance reference | | `static` | Static field declaration | | `struct` | *Reserved for future use* | | `true` | Boolean literal | | `void` | No return type | | `while` | While loop | --- ## 14. Operators ### 14.1 Operator Precedence (Highest to Lowest) | Precedence | Operators | Associativity | |------------|-----------|---------------| | 1 | `()` `[]` `.` `::` | Left to right | | 2 | `!` `~` `&` `*` (unary) `-` (unary) | Right to left | | 3 | `as` | Left to right | | 4 | `*` `/` `%` | Left to right | | 5 | `+` `-` | Left to right | | 6 | `<<` `>>` | Left to right | | 7 | `&` | Left to right | | 8 | `^` | Left to right | | 9 | `|` | Left to right | | 10 | `==` `!=` `<` `>` `<=` `>=` | Left to right | | 11 | `&&` | Left to right | | 12 | `||` | Left to right | | 13 | `=` `+=` `-=` `*=` `/=` | Right to left | ### 14.2 Operator Summary #### Arithmetic Operators ```rust + Addition - Subtraction * Multiplication / Division % Modulo ``` #### Comparison Operators ```rust == Equal != Not equal < Less than > Greater than <= Less than or equal >= Greater than or equal ``` #### Logical Operators ```rust && Logical AND || Logical OR ! Logical NOT ``` #### Bitwise Operators ```rust & Bitwise AND | Bitwise OR ^ Bitwise XOR ~ Bitwise NOT << Left shift >> Right shift ``` #### Memory Operators ```rust & Address-of * Dereference ``` #### Assignment Operators ```rust = Assignment += Add and assign -= Subtract and assign *= Multiply and assign /= Divide and assign ``` --- ## 15. Complete Example Programs ### 15.1 Hello World ```rust include print: "./lib/io/print.dsa"; fn main() -> void { print::println("Hello, world!"); } ``` ### 15.2 Vector Implementation ```rust include alloc: "./lib/memory/alloc.dsa"; class Vec { priv field data: &T; priv field len: u32; priv field capacity: u32; pub const DEFAULT_CAPACITY: u32 = 16; pub fn new(capacity: u32) -> Vec { let size: u32 = capacity * 4; // Assume sizeof(T) = 4 return Vec { data: alloc::malloc(size) as &T, len: 0, capacity: capacity }; } pub fn push(self: &Vec, item: T) { if self.len >= self.capacity { self.resize(); } *(self.data + self.len) = item; self.len = self.len + 1; } pub fn get(self: &Vec, index: u32) -> T { return *(self.data + index); } pub fn len(self: &Vec) -> u32 { return self.len; } priv fn resize(self: &Vec) { let new_capacity: u32 = self.capacity * 2; let new_size: u32 = new_capacity * 4; let new_data: &T = alloc::malloc(new_size) as &T; let mut i: u32 = 0; while i < self.len { *(new_data + i) = *(self.data + i); i = i + 1; } alloc::free(self.data as u32); self.data = new_data; self.capacity = new_capacity; } pub fn drop(self: &Vec) { alloc::free(self.data as u32); } } fn main() -> void { let vec: Vec = Vec::new(10); defer vec.drop(); vec.push(1); vec.push(2); vec.push(3); let mut i: u32 = 0; while i < vec.len() { let value: u32 = vec.get(i); // Use value... i = i + 1; } } ``` ### 15.3 Resource Management Example ```rust include alloc: "./lib/memory/alloc.dsa"; include print: "./lib/io/print.dsa"; class File { priv field handle: u32; priv field is_open: bool; pub fn open(path: str) -> File { let handle: u32 = 0; // Platform-specific open return File { handle: handle, is_open: true }; } pub fn write(self: &File, data: str) { if !self.is_open { return; } // Write implementation... } pub fn close(self: &File) { if self.is_open { // Platform-specific close self.is_open = false; } } } fn process_file(path: str) -> bool { let file: File = File::open(path); defer file.close(); // Ensures file is closed on all exit paths let buffer: u32 = alloc::malloc(1024); defer alloc::free(buffer); if !file.is_open { print::println("Failed to open file"); return false; // Defers run: free(buffer), file.close() } file.write("Hello, file!"); return true; // Defers run: free(buffer), file.close() } fn main() -> void { let success: bool = process_file("output.txt"); if success { print::println("File processed successfully"); } else { print::println("File processing failed"); } } ``` --- ## 16. Grammar Summary ### 16.1 EBNF Grammar ```ebnf program = { import_statement | class_definition | function_definition } import_statement = "include" identifier ":" string_literal ";" class_definition = "class" identifier [ generic_params ] "{" { class_member } "}" class_member = field_declaration | const_declaration | static_declaration | method_declaration field_declaration = visibility "field" identifier ":" type ";" const_declaration = visibility "const" IDENTIFIER ":" type "=" expression ";" static_declaration = visibility "static" "mut" identifier ":" type "=" expression ";" method_declaration = visibility "fn" identifier [ generic_params ] "(" parameters ")" [ "->" type ] block function_definition = "fn" identifier [ generic_params ] "(" parameters ")" [ "->" type ] block generic_params = "<" identifier { "," identifier } ">" parameters = [ parameter { "," parameter } ] parameter = identifier ":" type visibility = "pub" | "priv" type = primitive_type | pointer_type | array_type | generic_type | identifier primitive_type = "u8" | "u16" | "u32" | "u64" | "i8" | "i16" | "i32" | "i64" | "bool" | "str" | "void" pointer_type = "&" type array_type = "[" type ";" integer_literal "]" generic_type = identifier "<" type { "," type } ">" block = "{" { statement } "}" statement = let_statement | expression_statement | if_statement | while_statement | loop_statement | return_statement | defer_statement | break_statement | continue_statement let_statement = "let" [ "mut" ] identifier ":" type "=" expression ";" defer_statement = "defer" expression ";" if_statement = "if" expression block [ "else" ( if_statement | block ) ] while_statement = "while" expression block loop_statement = "loop" block return_statement = "return" [ expression ] ";" break_statement = "break" ";" continue_statement = "continue" ";" expression_statement = expression ";" expression = assignment_expression assignment_expression = logical_or_expression [ assignment_operator assignment_expression ] assignment_operator = "=" | "+=" | "-=" | "*=" | "/=" logical_or_expression = logical_and_expression { "||" logical_and_expression } logical_and_expression = equality_expression { "&&" equality_expression } equality_expression = relational_expression { equality_operator relational_expression } equality_operator = "==" | "!=" relational_expression = bitwise_or_expression { relational_operator bitwise_or_expression } relational_operator = "<" | ">" | "<=" | ">=" bitwise_or_expression = bitwise_xor_expression { "|" bitwise_xor_expression } bitwise_xor_expression = bitwise_and_expression { "^" bitwise_and_expression } bitwise_and_expression = shift_expression { "&" shift_expression } shift_expression = additive_expression { shift_operator additive_expression } shift_operator = "<<" | ">>" additive_expression = multiplicative_expression { additive_operator multiplicative_expression } additive_operator = "+" | "-" multiplicative_expression = cast_expression { multiplicative_operator cast_expression } multiplicative_operator = "*" | "/" | "%" cast_expression = unary_expression [ "as" type ] unary_expression = postfix_expression | unary_operator unary_expression unary_operator = "!" | "~" | "&" | "*" | "-" postfix_expression = primary_expression { postfix_operator } postfix_operator = "." identifier [ call_suffix ] | "::" identifier [ call_suffix ] | "[" expression "]" | call_suffix call_suffix = "(" [ arguments ] ")" arguments = expression { "," expression } primary_expression = identifier | literal | "(" expression ")" | struct_literal struct_literal = identifier "{" [ field_init { "," field_init } ] "}" field_init = identifier ":" expression literal = integer_literal | string_literal | boolean_literal boolean_literal = "true" | "false" ``` --- ## Appendix A: Differences from Rust While DSC uses Rust-like syntax, there are key differences: | Feature | Rust | DSC | |---------|------|-----| | **Encapsulation** | `struct` + `impl` | `class` | | **Field syntax** | `field: Type` | `field field: Type;` | | **References** | Borrow-checked `&T` | Raw pointers `&T` | | **Ownership** | Compile-time borrow checker | Manual with `defer` | | **Traits** | Supported | Not supported | | **Lifetimes** | Supported | Not supported | | **Pattern matching** | Supported | Not supported | | **Enums** | Sum types with data | Not yet supported | | **Modules** | Native | Assembly imports only | --- ## Appendix B: Standard Library Conventions By convention, standard library modules should provide: ### Allocation Module (`alloc`) ```rust include alloc: "./lib/memory/alloc.dsa"; // Functions: // alloc::malloc(size: u32) -> u32 // alloc::free(ptr: u32) -> void ``` ### Print Module (`print`) ```rust include print: "./lib/io/print.dsa"; // Functions: // print::print(msg: str) -> void // print::println(msg: str) -> void // print::print_num(n: u32) -> void // print::print_hex(n: u32) -> void ``` --- *End of DSC Language Specification v1.0*