diff --git a/docs/dsc-language-spec.md b/docs/dsc-language-spec.md new file mode 100644 index 0000000..1b99dc5 --- /dev/null +++ b/docs/dsc-language-spec.md @@ -0,0 +1,1223 @@ +# 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*