├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── samples ├── array.c ├── const.c ├── define.c ├── dowhile.c ├── fib.c ├── for.c ├── for2.c ├── logical.c ├── pointer.c ├── sample.c ├── string.c ├── struct.c ├── switch.c ├── typedef.c └── while.c ├── src ├── ast │ ├── declarator.rs │ ├── expression.rs │ ├── mod.rs │ ├── parser.rs │ ├── statement.rs │ └── typename.rs ├── main.rs ├── preprocess │ ├── context.rs │ ├── expression.rs │ ├── mod.rs │ ├── parser.rs │ └── preprocessor.rs ├── token │ ├── character.rs │ ├── identifier.rs │ ├── mod.rs │ ├── numeric.rs │ ├── string.rs │ ├── token.rs │ ├── tokenize.rs │ └── trie.rs └── virtualmachine │ ├── function.rs │ ├── instruction │ ├── generation.rs │ ├── mod.rs │ └── operand.rs │ ├── mod.rs │ ├── program.rs │ ├── scope.rs │ └── variable.rs └── tree.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | debug/ 4 | target/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | #Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | 13 | # MSVC Windows builds of rustc generate these, which store debugging information 14 | *.pdb 15 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "mini-c-parser" 7 | version = "0.12.2" 8 | dependencies = [ 9 | "rusty_parser", 10 | ] 11 | 12 | [[package]] 13 | name = "rusty_parser" 14 | version = "1.1.0" 15 | source = "registry+https://github.com/rust-lang/crates.io-index" 16 | checksum = "a0d4bd88bbc485acc1f3d26157ad5dd519e08c0e5a265a9601a8245b4eb195cd" 17 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mini-c-parser" 3 | version = "0.12.2" 4 | edition = "2021" 5 | license = "MIT" 6 | description = "minimal C language lexer & parser & virtual executer from scratch" 7 | repository = "https://github.com/ehwan/C-language-Parser-In-Rust" 8 | readme = "README.md" 9 | keywords = ["parser", "lexer", "c", "interpreter", "compiler"] 10 | categories = ["parser-implementations", "compilers"] 11 | 12 | [dependencies] 13 | rusty_parser = "1.1.0" 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Taehwan Kim 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # C language lexer & parser & virtual executer written in Rust 2 | 3 | C language lexer & parser & virtual executer from scratch in Rust. 4 | 5 | ## syntax not supported 6 | - `#include` 7 | - `#pragma` 8 | - `union` 9 | - `enum` 10 | - type qualifiers (`volatile`, `restrict` `static` `extern`) 11 | 12 | ## Features 13 | - Tokenizer (Lexer) 14 | - Preprocessor 15 | - Parser ( AST Builder ) 16 | - Code Generator 17 | - Virtual Machine (Instruction Executor) 18 | 19 | ## How it works 20 | ### Phase 1: Tokenizing 21 | Tokenize the raw source code into a list of tokens. 22 | This phase will remove c/cpp comments. 23 | Sequence of whitespaces will be combined into one `Token::Whitespace` 24 | The newline `\n` will be kept as a `Token::NewLine` for later phase 25 | If the source is not end with `\n`, it will be added automatically 26 | 27 | ### Phase 2: Line Analysis 28 | Analyze the tokens in each line and generate a list of `Line` which contains the result of the analysis. This phase will extract preprocessor directives and macro definitions. 29 | 30 | ### Phase 3: Preprocessing 31 | Preprocess the source code by expanding macros and removing preprocessor directives. 32 | 33 | ### Phase 4: Building AbstractSyntaxTree 34 | Build an Abstract Syntax Tree (AST) from the preprocessed token stream. The AST will be used to generate instructions. 35 | 36 | ### Phase 5: Generating Instructions 37 | Generate a sequence of virtual instructions from the AST. The instructions will be executed at the software level. 38 | 39 | ### Phase 6: Executing Instructions 40 | Execute the generated instructions. The virtual machine will simulate the execution of the code. 41 | 42 | ### Note 43 | This process will not generate binary or assembly code. Instead, it will produce a sequence of virtual instructions (`src/virtualmachine/instruction`) which will be executed at the software level. 44 | 45 | 46 | ## How to run 47 | ```sh 48 | cargo run 49 | ``` 50 | To execute the program, pass the C code to stdin. 51 | Once you are done, press ^D to finish the input. The program will tokenize, parse, generate instructions, and execute the code. 52 | 53 | 54 | Sample C codes (only with implemented features) are in `samples/` directory. Try them with `cat samples/sample.c | cargo run` 55 | 56 | ## Example 57 | ```c 58 | /// samples/sample.c 59 | 60 | // declaration of function fibonacci sequence 61 | int fibonacci(int); 62 | 63 | #define MY_MACRO_FUNC(x, y) y + x 64 | 65 | #if MY_MACRO_FUNC(1, 2) == 3 66 | 67 | // main function 68 | int main() 69 | { 70 | print_str("Hello, World!"); // built in function 'print_str' 71 | int var = 10; 72 | int* ptr = &var; 73 | *ptr = MY_MACRO_FUNC(40, 60); 74 | print(ptr, *ptr, var); // built in function 'print' 75 | 76 | print(MY_MACRO_FUNC(10, 20)); 77 | 78 | // print fibonacci sequence 79 | print_str("Fibonacci sequence:"); 80 | int i; 81 | for (i = 1; i <= 10; i++) 82 | { 83 | print(i, fibonacci(i)); 84 | } 85 | 86 | return 0; 87 | } 88 | 89 | // definition of function fibonacci sequence using recursion 90 | int fibonacci(int n) 91 | { 92 | if (n <= 2) 93 | return 1; 94 | else 95 | return fibonacci(n - 1) + fibonacci(n - 2); 96 | } 97 | 98 | #else 99 | 100 | THIS WILL BE IGNORED 101 | 102 | #endif 103 | ``` 104 | 105 | Pass c code to stdin 106 | ```sh 107 | cat samples/sample.c | cargo run 108 | ``` 109 | 110 | The result will be: 111 | 112 | ``` 113 | Enter your code (and ^D for EOF): 114 | ================================================================================ 115 | ===============================Phase1: Tokenizing=============================== 116 | ================================================================================ 117 | LINE | ---------------------------------Result---------------------------------- 118 | 0: 119 | 1: Identifier("int") Whitespace Identifier("fibonacci") LeftParen Identifier("int") RightParen SemiColon 120 | 2: 121 | 3: PreprocessorDefine Whitespace Identifier("MY_MACRO_FUNC") LeftParen Identifier("x") Comma Whitespace Identifier("y") RightParen Whitespace Identifier("y") Whitespace Plus Whitespace Identifier("x") 122 | 4: 123 | 5: PreprocessorIf Whitespace Identifier("MY_MACRO_FUNC") LeftParen ConstantInteger(1) Comma Whitespace ConstantInteger(2) RightParen Whitespace EqOp Whitespace ConstantInteger(3) 124 | 6: 125 | 7: 126 | 8: Identifier("int") Whitespace Identifier("main") LeftParen RightParen 127 | 9: LeftBrace 128 | 10: Whitespace Identifier("print_str") LeftParen StringLiteral("Hello, World!") RightParen SemiColon Whitespace 129 | 11: Whitespace Identifier("int") Whitespace Identifier("var") Whitespace Equal Whitespace ConstantInteger(10) SemiColon 130 | 12: Whitespace Identifier("int") Star Whitespace Identifier("ptr") Whitespace Equal Whitespace Ampersand Identifier("var") SemiColon 131 | 13: Whitespace Star Identifier("ptr") Whitespace Equal Whitespace Identifier("MY_MACRO_FUNC") LeftParen ConstantInteger(40) Comma Whitespace ConstantInteger(60) RightParen SemiColon 132 | 14: Whitespace Identifier("print") LeftParen Identifier("ptr") Comma Whitespace Star Identifier("ptr") Comma Whitespace Identifier("var") RightParen SemiColon Whitespace 133 | 15: 134 | 16: Whitespace Identifier("print") LeftParen Identifier("MY_MACRO_FUNC") LeftParen ConstantInteger(10) Comma Whitespace ConstantInteger(20) RightParen RightParen SemiColon 135 | 17: 136 | 18: Whitespace 137 | 19: Whitespace Identifier("print_str") LeftParen StringLiteral("Fibonacci sequence:") RightParen SemiColon 138 | 20: Whitespace Identifier("int") Whitespace Identifier("i") SemiColon 139 | 21: Whitespace Identifier("for") Whitespace LeftParen Identifier("i") Whitespace Equal Whitespace ConstantInteger(1) SemiColon Whitespace Identifier("i") Whitespace LeOp Whitespace ConstantInteger(10) SemiColon Whitespace Identifier("i") IncOp RightParen 140 | 22: Whitespace LeftBrace 141 | 23: Whitespace Identifier("print") LeftParen Identifier("i") Comma Whitespace Identifier("fibonacci") LeftParen Identifier("i") RightParen RightParen SemiColon 142 | 24: Whitespace RightBrace 143 | 25: 144 | 26: Whitespace Identifier("return") Whitespace ConstantInteger(0) SemiColon 145 | 27: RightBrace 146 | 28: 147 | 29: 148 | 30: Identifier("int") Whitespace Identifier("fibonacci") LeftParen Identifier("int") Whitespace Identifier("n") RightParen 149 | 31: LeftBrace 150 | 32: Whitespace Identifier("if") Whitespace LeftParen Identifier("n") Whitespace LeOp Whitespace ConstantInteger(2) RightParen 151 | 33: Whitespace Identifier("return") Whitespace ConstantInteger(1) SemiColon 152 | 34: Whitespace Identifier("else") 153 | 35: Whitespace Identifier("return") Whitespace Identifier("fibonacci") LeftParen Identifier("n") Whitespace Minus Whitespace ConstantInteger(1) RightParen Whitespace Plus Whitespace Identifier("fibonacci") LeftParen Identifier("n") Whitespace Minus Whitespace ConstantInteger(2) RightParen SemiColon 154 | 36: RightBrace 155 | 37: 156 | 38: PreprocessorElse 157 | 39: 158 | 40: Identifier("THIS") Whitespace Identifier("WILL") Whitespace Identifier("BE") Whitespace Identifier("IGNORED") 159 | 41: 160 | 42: PreprocessorEndIf 161 | ================================================================================ 162 | =============================Phase2: Line Analysis============================== 163 | ================================================================================ 164 | LINE | ---------------------------------Result---------------------------------- 165 | 0: RawTokens { tokens: [Identifier("int"), Identifier("fibonacci"), LeftParen, Identifier("int"), RightParen, SemiColon] } 166 | 1: DefineFunction { name: "MY_MACRO_FUNC", param_count: 2, replacement: [PreprocessorPlaceholder(1), Plus, PreprocessorPlaceholder(0)] } 167 | 2: If { expression_tokens: [Identifier("MY_MACRO_FUNC"), LeftParen, ConstantInteger(1), Comma, ConstantInteger(2), RightParen, EqOp, ConstantInteger(3)] } 168 | 3: RawTokens { tokens: [Identifier("int"), Identifier("main"), LeftParen, RightParen] } 169 | 4: RawTokens { tokens: [LeftBrace] } 170 | 5: RawTokens { tokens: [Identifier("print_str"), LeftParen, StringLiteral("Hello, World!"), RightParen, SemiColon] } 171 | 6: RawTokens { tokens: [Identifier("int"), Identifier("var"), Equal, ConstantInteger(10), SemiColon] } 172 | 7: RawTokens { tokens: [Identifier("int"), Star, Identifier("ptr"), Equal, Ampersand, Identifier("var"), SemiColon] } 173 | 8: RawTokens { tokens: [Star, Identifier("ptr"), Equal, Identifier("MY_MACRO_FUNC"), LeftParen, ConstantInteger(40), Comma, ConstantInteger(60), RightParen, SemiColon] } 174 | 9: RawTokens { tokens: [Identifier("print"), LeftParen, Identifier("ptr"), Comma, Star, Identifier("ptr"), Comma, Identifier("var"), RightParen, SemiColon] } 175 | 10: RawTokens { tokens: [Identifier("print"), LeftParen, Identifier("MY_MACRO_FUNC"), LeftParen, ConstantInteger(10), Comma, ConstantInteger(20), RightParen, RightParen, SemiColon] } 176 | 11: RawTokens { tokens: [Identifier("print_str"), LeftParen, StringLiteral("Fibonacci sequence:"), RightParen, SemiColon] } 177 | 12: RawTokens { tokens: [Identifier("int"), Identifier("i"), SemiColon] } 178 | 13: RawTokens { tokens: [Identifier("for"), LeftParen, Identifier("i"), Equal, ConstantInteger(1), SemiColon, Identifier("i"), LeOp, ConstantInteger(10), SemiColon, Identifier("i"), IncOp, RightParen] } 179 | 14: RawTokens { tokens: [LeftBrace] } 180 | 15: RawTokens { tokens: [Identifier("print"), LeftParen, Identifier("i"), Comma, Identifier("fibonacci"), LeftParen, Identifier("i"), RightParen, RightParen, SemiColon] } 181 | 16: RawTokens { tokens: [RightBrace] } 182 | 17: RawTokens { tokens: [Identifier("return"), ConstantInteger(0), SemiColon] } 183 | 18: RawTokens { tokens: [RightBrace] } 184 | 19: RawTokens { tokens: [Identifier("int"), Identifier("fibonacci"), LeftParen, Identifier("int"), Identifier("n"), RightParen] } 185 | 20: RawTokens { tokens: [LeftBrace] } 186 | 21: RawTokens { tokens: [Identifier("if"), LeftParen, Identifier("n"), LeOp, ConstantInteger(2), RightParen] } 187 | 22: RawTokens { tokens: [Identifier("return"), ConstantInteger(1), SemiColon] } 188 | 23: RawTokens { tokens: [Identifier("else")] } 189 | 24: RawTokens { tokens: [Identifier("return"), Identifier("fibonacci"), LeftParen, Identifier("n"), Minus, ConstantInteger(1), RightParen, Plus, Identifier("fibonacci"), LeftParen, Identifier("n"), Minus, ConstantInteger(2), RightParen, SemiColon] } 190 | 25: RawTokens { tokens: [RightBrace] } 191 | 26: Else 192 | 27: RawTokens { tokens: [Identifier("THIS"), Identifier("WILL"), Identifier("BE"), Identifier("IGNORED")] } 193 | 28: EndIf 194 | ================================================================================ 195 | =============================Phase3: Preprocessing============================== 196 | ================================================================================ 197 | LINE | ---------------------------------Result---------------------------------- 198 | 0: [Int, Identifier("fibonacci"), LeftParen, Int, RightParen, SemiColon] 199 | 1: [Int, Identifier("main"), LeftParen, RightParen] 200 | 2: [LeftBrace] 201 | 3: [Identifier("print_str"), LeftParen, StringLiteral("Hello, World!"), RightParen, SemiColon] 202 | 4: [Int, Identifier("var"), Equal, ConstantInteger(10), SemiColon] 203 | 5: [Int, Star, Identifier("ptr"), Equal, Ampersand, Identifier("var"), SemiColon] 204 | 6: [Star, Identifier("ptr"), Equal, ConstantInteger(60), Plus, ConstantInteger(40), SemiColon] 205 | 7: [Identifier("print"), LeftParen, Identifier("ptr"), Comma, Star, Identifier("ptr"), Comma, Identifier("var"), RightParen, SemiColon] 206 | 8: [Identifier("print"), LeftParen, ConstantInteger(20), Plus, ConstantInteger(10), RightParen, SemiColon] 207 | 9: [Identifier("print_str"), LeftParen, StringLiteral("Fibonacci sequence:"), RightParen, SemiColon] 208 | 10: [Int, Identifier("i"), SemiColon] 209 | 11: [For, LeftParen, Identifier("i"), Equal, ConstantInteger(1), SemiColon, Identifier("i"), LeOp, ConstantInteger(10), SemiColon, Identifier("i"), IncOp, RightParen] 210 | 12: [LeftBrace] 211 | 13: [Identifier("print"), LeftParen, Identifier("i"), Comma, Identifier("fibonacci"), LeftParen, Identifier("i"), RightParen, RightParen, SemiColon] 212 | 14: [RightBrace] 213 | 15: [Return, ConstantInteger(0), SemiColon] 214 | 16: [RightBrace] 215 | 17: [Int, Identifier("fibonacci"), LeftParen, Int, Identifier("n"), RightParen] 216 | 18: [LeftBrace] 217 | 19: [If, LeftParen, Identifier("n"), LeOp, ConstantInteger(2), RightParen] 218 | 20: [Return, ConstantInteger(1), SemiColon] 219 | 21: [Else] 220 | 22: [Return, Identifier("fibonacci"), LeftParen, Identifier("n"), Minus, ConstantInteger(1), RightParen, Plus, Identifier("fibonacci"), LeftParen, Identifier("n"), Minus, ConstantInteger(2), RightParen, SemiColon] 221 | 23: [RightBrace] 222 | ================================================================================ 223 | ======================Phase4: Building AbstractSyntaxTree======================= 224 | ================================================================================ 225 | ASTs: 226 | TranslationUnit { 227 | statements: [ 228 | FunctionDeclaration { 229 | return_type: Int32, 230 | name: "fibonacci", 231 | params: [ 232 | Int32, 233 | ], 234 | }, 235 | FunctionDefinitionStatement { 236 | return_type: Int32, 237 | name: "main", 238 | params: [], 239 | body: CompoundStatement { 240 | statements: [ 241 | ExpressionStatement { 242 | expression: PostParen { 243 | src: PrimaryIdentifier { 244 | name: "print_str", 245 | }, 246 | args: [ 247 | StringLiteral { 248 | value: "Hello, World!", 249 | }, 250 | ], 251 | }, 252 | }, 253 | DeclarationStatement { 254 | vars: [ 255 | ( 256 | "var", 257 | Int32, 258 | Some( 259 | ConstantInteger { 260 | value: 10, 261 | }, 262 | ), 263 | ), 264 | ], 265 | }, 266 | DeclarationStatement { 267 | vars: [ 268 | ( 269 | "ptr", 270 | Pointer( 271 | Int32, 272 | ), 273 | Some( 274 | UnaryExpression { 275 | op: AddressOf, 276 | src: PrimaryIdentifier { 277 | name: "var", 278 | }, 279 | }, 280 | ), 281 | ), 282 | ], 283 | }, 284 | ExpressionStatement { 285 | expression: AssignExpression { 286 | lhs: UnaryExpression { 287 | op: Dereference, 288 | src: PrimaryIdentifier { 289 | name: "ptr", 290 | }, 291 | }, 292 | rhs: AdditiveExpression { 293 | op: Add, 294 | lhs: ConstantInteger { 295 | value: 60, 296 | }, 297 | rhs: ConstantInteger { 298 | value: 40, 299 | }, 300 | }, 301 | }, 302 | }, 303 | ExpressionStatement { 304 | expression: PostParen { 305 | src: PrimaryIdentifier { 306 | name: "print", 307 | }, 308 | args: [ 309 | PrimaryIdentifier { 310 | name: "ptr", 311 | }, 312 | UnaryExpression { 313 | op: Dereference, 314 | src: PrimaryIdentifier { 315 | name: "ptr", 316 | }, 317 | }, 318 | PrimaryIdentifier { 319 | name: "var", 320 | }, 321 | ], 322 | }, 323 | }, 324 | ExpressionStatement { 325 | expression: PostParen { 326 | src: PrimaryIdentifier { 327 | name: "print", 328 | }, 329 | args: [ 330 | AdditiveExpression { 331 | op: Add, 332 | lhs: ConstantInteger { 333 | value: 20, 334 | }, 335 | rhs: ConstantInteger { 336 | value: 10, 337 | }, 338 | }, 339 | ], 340 | }, 341 | }, 342 | ExpressionStatement { 343 | expression: PostParen { 344 | src: PrimaryIdentifier { 345 | name: "print_str", 346 | }, 347 | args: [ 348 | StringLiteral { 349 | value: "Fibonacci sequence:", 350 | }, 351 | ], 352 | }, 353 | }, 354 | DeclarationStatement { 355 | vars: [ 356 | ( 357 | "i", 358 | Int32, 359 | None, 360 | ), 361 | ], 362 | }, 363 | ForStatement { 364 | init: AssignExpression { 365 | lhs: PrimaryIdentifier { 366 | name: "i", 367 | }, 368 | rhs: ConstantInteger { 369 | value: 1, 370 | }, 371 | }, 372 | cond: ComparisonExpression { 373 | op: LessThanOrEqual, 374 | lhs: PrimaryIdentifier { 375 | name: "i", 376 | }, 377 | rhs: ConstantInteger { 378 | value: 10, 379 | }, 380 | }, 381 | next: Some( 382 | PostIncrement { 383 | src: PrimaryIdentifier { 384 | name: "i", 385 | }, 386 | }, 387 | ), 388 | statement: CompoundStatement { 389 | statements: [ 390 | ExpressionStatement { 391 | expression: PostParen { 392 | src: PrimaryIdentifier { 393 | name: "print", 394 | }, 395 | args: [ 396 | PrimaryIdentifier { 397 | name: "i", 398 | }, 399 | PostParen { 400 | src: PrimaryIdentifier { 401 | name: "fibonacci", 402 | }, 403 | args: [ 404 | PrimaryIdentifier { 405 | name: "i", 406 | }, 407 | ], 408 | }, 409 | ], 410 | }, 411 | }, 412 | ], 413 | }, 414 | }, 415 | ReturnStatement { 416 | expr: Some( 417 | ConstantInteger { 418 | value: 0, 419 | }, 420 | ), 421 | }, 422 | ], 423 | }, 424 | }, 425 | FunctionDefinitionStatement { 426 | return_type: Int32, 427 | name: "fibonacci", 428 | params: [ 429 | ( 430 | Some( 431 | "n", 432 | ), 433 | Int32, 434 | ), 435 | ], 436 | body: CompoundStatement { 437 | statements: [ 438 | IfStatement { 439 | cond: ComparisonExpression { 440 | op: LessThanOrEqual, 441 | lhs: PrimaryIdentifier { 442 | name: "n", 443 | }, 444 | rhs: ConstantInteger { 445 | value: 2, 446 | }, 447 | }, 448 | then_statement: ReturnStatement { 449 | expr: Some( 450 | ConstantInteger { 451 | value: 1, 452 | }, 453 | ), 454 | }, 455 | else_statement: Some( 456 | ReturnStatement { 457 | expr: Some( 458 | AdditiveExpression { 459 | op: Add, 460 | lhs: PostParen { 461 | src: PrimaryIdentifier { 462 | name: "fibonacci", 463 | }, 464 | args: [ 465 | AdditiveExpression { 466 | op: Sub, 467 | lhs: PrimaryIdentifier { 468 | name: "n", 469 | }, 470 | rhs: ConstantInteger { 471 | value: 1, 472 | }, 473 | }, 474 | ], 475 | }, 476 | rhs: PostParen { 477 | src: PrimaryIdentifier { 478 | name: "fibonacci", 479 | }, 480 | args: [ 481 | AdditiveExpression { 482 | op: Sub, 483 | lhs: PrimaryIdentifier { 484 | name: "n", 485 | }, 486 | rhs: ConstantInteger { 487 | value: 2, 488 | }, 489 | }, 490 | ], 491 | }, 492 | }, 493 | ), 494 | }, 495 | ), 496 | }, 497 | ], 498 | }, 499 | }, 500 | ], 501 | } 502 | ================================================================================ 503 | ========================Phase5: Generating Instructions========================= 504 | ================================================================================ 505 | ADDR | ---------------------------------Result---------------------------------- 506 | Instructions: 507 | 0: DefineLabel { label: "main" } 508 | 1: PushStack { operand: Register(5) } 509 | 2: MoveRegister { operand_from: Register(6), operand_to: Register(5) } 510 | 3: MoveRegister { operand_from: Value(UInt64(0)), operand_to: Register(0) } 511 | 4: PrintStr { str: Register(0) } 512 | 5: MoveRegister { operand_from: Value(Int32(10)), operand_to: Register(0) } 513 | 6: Assign { lhs_type: Int32, lhs: Register(1), rhs: Register(0) } 514 | 7: PushStack { operand: Register(1) } 515 | 8: MoveRegister { operand_from: Register(5), operand_to: Register(0) } 516 | 9: AddAssign { lhs: Register(0), rhs: Value(Int64(0)) } 517 | 10: Assign { lhs_type: Pointer(Int32), lhs: Register(1), rhs: Register(0) } 518 | 11: PushStack { operand: Register(1) } 519 | 12: MoveRegister { operand_from: Value(Int32(40)), operand_to: Register(0) } 520 | 13: PushStack { operand: Register(0) } 521 | 14: MoveRegister { operand_from: Value(Int32(60)), operand_to: Register(0) } 522 | 15: Assign { lhs_type: UInt32, lhs: Register(0), rhs: Register(0) } 523 | 16: PopStack { operand: Register(1) } 524 | 17: AddAssign { lhs: Register(0), rhs: Register(1) } 525 | 18: PushStack { operand: Register(0) } 526 | 19: MoveRegister { operand_from: Register(5), operand_to: Register(0) } 527 | 20: AddAssign { lhs: Register(0), rhs: Value(Int64(1)) } 528 | 21: MoveRegister { operand_from: Derefed(0, 0), operand_to: Register(0) } 529 | 22: PopStack { operand: Register(1) } 530 | 23: Assign { lhs_type: Int32, lhs: Derefed(0, 0), rhs: Register(1) } 531 | 24: MoveRegister { operand_from: Register(5), operand_to: Register(0) } 532 | 25: AddAssign { lhs: Register(0), rhs: Value(Int64(0)) } 533 | 26: PushStack { operand: Derefed(0, 0) } 534 | 27: MoveRegister { operand_from: Register(5), operand_to: Register(0) } 535 | 28: AddAssign { lhs: Register(0), rhs: Value(Int64(1)) } 536 | 29: MoveRegister { operand_from: Derefed(0, 0), operand_to: Register(0) } 537 | 30: PushStack { operand: Derefed(0, 0) } 538 | 31: MoveRegister { operand_from: Register(5), operand_to: Register(0) } 539 | 32: AddAssign { lhs: Register(0), rhs: Value(Int64(1)) } 540 | 33: PushStack { operand: Derefed(0, 0) } 541 | 34: PushStack { operand: Value(UInt64(3)) } 542 | 35: Print 543 | 36: MoveRegister { operand_from: Value(Int32(10)), operand_to: Register(0) } 544 | 37: PushStack { operand: Register(0) } 545 | 38: MoveRegister { operand_from: Value(Int32(20)), operand_to: Register(0) } 546 | 39: Assign { lhs_type: UInt32, lhs: Register(0), rhs: Register(0) } 547 | 40: PopStack { operand: Register(1) } 548 | 41: AddAssign { lhs: Register(0), rhs: Register(1) } 549 | 42: PushStack { operand: Register(0) } 550 | 43: PushStack { operand: Value(UInt64(1)) } 551 | 44: Print 552 | 45: MoveRegister { operand_from: Value(UInt64(14)), operand_to: Register(0) } 553 | 46: PrintStr { str: Register(0) } 554 | 47: PushStack { operand: Value(Int32(0)) } 555 | 48: MoveRegister { operand_from: Value(Int32(1)), operand_to: Register(0) } 556 | 49: PushStack { operand: Register(0) } 557 | 50: MoveRegister { operand_from: Register(5), operand_to: Register(0) } 558 | 51: AddAssign { lhs: Register(0), rhs: Value(Int64(2)) } 559 | 52: PopStack { operand: Register(1) } 560 | 53: Assign { lhs_type: Int32, lhs: Derefed(0, 0), rhs: Register(1) } 561 | 54: DefineLabel { label: ".__L0__" } 562 | 55: MoveRegister { operand_from: Register(5), operand_to: Register(0) } 563 | 56: AddAssign { lhs: Register(0), rhs: Value(Int64(2)) } 564 | 57: PushStack { operand: Derefed(0, 0) } 565 | 58: MoveRegister { operand_from: Value(Int32(10)), operand_to: Register(0) } 566 | 59: PopStack { operand: Register(1) } 567 | 60: LessThan { lhs: Register(0), rhs: Register(1), to: Register(0) } 568 | 61: LogicalNot { operand: Register(0) } 569 | 62: JumpZero { label: ".__L1__", operand_cond: Register(0) } 570 | 63: MoveRegister { operand_from: Register(5), operand_to: Register(0) } 571 | 64: AddAssign { lhs: Register(0), rhs: Value(Int64(2)) } 572 | 65: PushStack { operand: Derefed(0, 0) } 573 | 66: Call { label: "fibonacci" } 574 | 67: SubAssign { lhs: Register(6), rhs: Value(UInt64(1)) } 575 | 68: PushStack { operand: Register(0) } 576 | 69: MoveRegister { operand_from: Register(5), operand_to: Register(0) } 577 | 70: AddAssign { lhs: Register(0), rhs: Value(Int64(2)) } 578 | 71: PushStack { operand: Derefed(0, 0) } 579 | 72: PushStack { operand: Value(UInt64(2)) } 580 | 73: Print 581 | 74: DefineLabel { label: ".__L2__" } 582 | 75: MoveRegister { operand_from: Register(5), operand_to: Register(0) } 583 | 76: AddAssign { lhs: Register(0), rhs: Value(Int64(2)) } 584 | 77: MoveRegister { operand_from: Register(0), operand_to: Register(1) } 585 | 78: MoveRegister { operand_from: Derefed(1, 0), operand_to: Register(0) } 586 | 79: AddAssign { lhs: Derefed(1, 0), rhs: Value(UInt8(1)) } 587 | 80: Jump { label: ".__L0__" } 588 | 81: DefineLabel { label: ".__L1__" } 589 | 82: MoveRegister { operand_from: Value(Int32(0)), operand_to: Register(0) } 590 | 83: Return 591 | 84: Panic { message: "Function main must return a Int32 value" } 592 | 85: DefineLabel { label: "fibonacci" } 593 | 86: PushStack { operand: Register(5) } 594 | 87: MoveRegister { operand_from: Register(6), operand_to: Register(5) } 595 | 88: MoveRegister { operand_from: Register(5), operand_to: Register(0) } 596 | 89: AddAssign { lhs: Register(0), rhs: Value(Int64(-3)) } 597 | 90: PushStack { operand: Derefed(0, 0) } 598 | 91: MoveRegister { operand_from: Value(Int32(2)), operand_to: Register(0) } 599 | 92: PopStack { operand: Register(1) } 600 | 93: LessThan { lhs: Register(0), rhs: Register(1), to: Register(0) } 601 | 94: LogicalNot { operand: Register(0) } 602 | 95: JumpZero { label: ".__L3__", operand_cond: Register(0) } 603 | 96: MoveRegister { operand_from: Value(Int32(1)), operand_to: Register(0) } 604 | 97: Return 605 | 98: Jump { label: ".__L4__" } 606 | 99: DefineLabel { label: ".__L3__" } 607 | 100: MoveRegister { operand_from: Value(Int32(2)), operand_to: Register(0) } 608 | 101: PushStack { operand: Register(0) } 609 | 102: MoveRegister { operand_from: Register(5), operand_to: Register(0) } 610 | 103: AddAssign { lhs: Register(0), rhs: Value(Int64(-3)) } 611 | 104: Assign { lhs_type: UInt32, lhs: Register(0), rhs: Derefed(0, 0) } 612 | 105: PopStack { operand: Register(1) } 613 | 106: SubAssign { lhs: Register(0), rhs: Register(1) } 614 | 107: PushStack { operand: Register(0) } 615 | 108: Call { label: "fibonacci" } 616 | 109: SubAssign { lhs: Register(6), rhs: Value(UInt64(1)) } 617 | 110: PushStack { operand: Register(0) } 618 | 111: MoveRegister { operand_from: Value(Int32(1)), operand_to: Register(0) } 619 | 112: PushStack { operand: Register(0) } 620 | 113: MoveRegister { operand_from: Register(5), operand_to: Register(0) } 621 | 114: AddAssign { lhs: Register(0), rhs: Value(Int64(-3)) } 622 | 115: Assign { lhs_type: UInt32, lhs: Register(0), rhs: Derefed(0, 0) } 623 | 116: PopStack { operand: Register(1) } 624 | 117: SubAssign { lhs: Register(0), rhs: Register(1) } 625 | 118: PushStack { operand: Register(0) } 626 | 119: Call { label: "fibonacci" } 627 | 120: SubAssign { lhs: Register(6), rhs: Value(UInt64(1)) } 628 | 121: Assign { lhs_type: UInt32, lhs: Register(0), rhs: Register(0) } 629 | 122: PopStack { operand: Register(1) } 630 | 123: AddAssign { lhs: Register(0), rhs: Register(1) } 631 | 124: Return 632 | 125: DefineLabel { label: ".__L4__" } 633 | 126: Panic { message: "Function fibonacci must return a Int32 value" } 634 | --------------------------------Start Address--------------------------------- 635 | 127: Call { label: "main" } 636 | ================================================================================ 637 | =========================Phase6: Executing Instructions========================= 638 | ================================================================================ 639 | "Hello, World!" 640 | Print: UInt64(36), Int32(100), Int32(100), 641 | Print: UInt32(30), 642 | "Fibonacci sequence:" 643 | Print: Int32(1), Int32(1), 644 | Print: Int32(2), Int32(1), 645 | Print: Int32(3), UInt32(2), 646 | Print: Int32(4), UInt32(3), 647 | Print: Int32(5), UInt32(5), 648 | Print: Int32(6), UInt32(8), 649 | Print: Int32(7), UInt32(13), 650 | Print: Int32(8), UInt32(21), 651 | Print: Int32(9), UInt32(34), 652 | Print: Int32(10), UInt32(55), 653 | ``` 654 | 655 | The visualized AST will be: 656 | 657 | ![AST](tree.png) 658 | 659 | ``` 660 | TranslationUnit 661 | ├── DeclarationStatement 662 | │ └── Vars 663 | │ └── (Some("fibonacci"), Function(Int32, [Int32]), None) 664 | ├── FunctionDefinitionStatement: main 665 | │ ├── ReturnType: Int32 666 | │ ├── Name: main 667 | │ ├── Params: [] 668 | │ └── Body: CompoundStatement 669 | │ ├── ExpressionStatement 670 | │ │ └── PostParen 671 | │ │ ├── Src: PrimaryIdentifier(print_str) 672 | │ │ └── Args: [StringLiteral("Hello, World!")] 673 | │ ├── DeclarationStatement 674 | │ │ └── Vars 675 | │ │ └── (Some("var"), Int32, ConstantInteger(10)) 676 | │ ├── DeclarationStatement 677 | │ │ └── Vars 678 | │ │ └── (Some("ptr"), Pointer(Int32), UnaryExpression(AddressOf, PrimaryIdentifier(var))) 679 | │ ├── ExpressionStatement 680 | │ │ └── AssignExpression 681 | │ │ ├── Op: Assign 682 | │ │ ├── Lhs: UnaryExpression(Dereference, PrimaryIdentifier(ptr)) 683 | │ │ └── Rhs: ConstantInteger(100) 684 | │ ├── ExpressionStatement 685 | │ │ └── PostParen 686 | │ │ ├── Src: PrimaryIdentifier(print) 687 | │ │ └── Args: [PrimaryIdentifier(ptr), UnaryExpression(Dereference, PrimaryIdentifier(ptr)), PrimaryIdentifier(var)] 688 | │ ├── ExpressionStatement 689 | │ │ └── PostParen 690 | │ │ ├── Src: PrimaryIdentifier(print_str) 691 | │ │ └── Args: [StringLiteral("Fibonacci sequence:")] 692 | │ ├── DeclarationStatement 693 | │ │ └── Vars 694 | │ │ └── (Some("i"), Int32, None) 695 | │ ├── ForStatement 696 | │ │ ├── Init: AssignExpression 697 | │ │ │ ├── Op: Assign 698 | │ │ │ ├── Lhs: PrimaryIdentifier(i) 699 | │ │ │ └── Rhs: ConstantInteger(1) 700 | │ │ ├── Cond: ComparisonExpression 701 | │ │ │ ├── Op: LessThanOrEqual 702 | │ │ │ ├── Lhs: PrimaryIdentifier(i) 703 | │ │ │ └── Rhs: ConstantInteger(10) 704 | │ │ ├── Next: PostIncrement(PrimaryIdentifier(i)) 705 | │ │ └── Statement: CompoundStatement 706 | │ │ └── ExpressionStatement 707 | │ │ └── PostParen 708 | │ │ ├── Src: PrimaryIdentifier(print) 709 | │ │ └── Args: [PrimaryIdentifier(i), PostParen(PrimaryIdentifier(fibonacci), [PrimaryIdentifier(i)])] 710 | │ └── ReturnStatement 711 | │ └── Expr: ConstantInteger(0) 712 | ├── FunctionDefinitionStatement: fibonacci 713 | │ ├── ReturnType: Int32 714 | │ ├── Name: fibonacci 715 | │ ├── Params: [(Some("n"), Int32)] 716 | │ └── Body: CompoundStatement 717 | │ └── IfStatement 718 | │ ├── Cond: ComparisonExpression 719 | │ │ ├── Op: LessThanOrEqual 720 | │ │ ├── Lhs: PrimaryIdentifier(n) 721 | │ │ └── Rhs: ConstantInteger(2) 722 | │ ├── Then: ReturnStatement 723 | │ │ └── Expr: ConstantInteger(1) 724 | │ └── Else: ReturnStatement 725 | │ └── Expr: AdditiveExpression 726 | │ ├── Op: Add 727 | │ ├── Lhs: PostParen(PrimaryIdentifier(fibonacci), [AdditiveExpression(Sub, PrimaryIdentifier(n), ConstantInteger(1))]) 728 | │ └── Rhs: PostParen(PrimaryIdentifier(fibonacci), [AdditiveExpression(Sub, PrimaryIdentifier(n), ConstantInteger(2))]) 729 | ``` -------------------------------------------------------------------------------- /samples/array.c: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int i; 4 | 5 | // array with 5 elements 6 | int arr1[] = { 1, 2, 3, 4, 5 }; 7 | 8 | for (i = 0; i < 5; i++) 9 | { 10 | print(arr1[i]); 11 | } 12 | // 1, 2, 3, 4, 5 13 | 14 | // array without initialization 15 | int arr2[5]; 16 | for (i = 0; i < 5; i++) 17 | { 18 | print(arr2[i]); 19 | } 20 | // 0, 0, 0, 0, 0 21 | 22 | // array with partial initialization 23 | // remaining elements will be initialized to 0 (default value) 24 | int arr3[5] = { 1, 2, 3 }; 25 | for (i = 0; i < 5; i++) 26 | { 27 | print(arr3[i]); 28 | } 29 | // 1, 2, 3, 0, 0 30 | 31 | // this will panic 32 | // int arr4[2] = { 1, 2, 3 }; 33 | 34 | int* arr_ptr = arr3; 35 | *arr_ptr = 10; 36 | ++arr_ptr; 37 | *arr_ptr = 20; 38 | *(arr_ptr + 1) = 30; 39 | arr_ptr[2] = 40; 40 | arr_ptr[3] = 50; 41 | for (i = 0; i < 5; i++) 42 | { 43 | print(arr3[i]); 44 | } 45 | // 10, 20, 30, 40, 50 46 | 47 | return 0; 48 | } -------------------------------------------------------------------------------- /samples/const.c: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | // const variable 4 | { 5 | int a = 10; 6 | int const b = 20; 7 | 8 | print(a, b); 9 | // 10, 20 10 | 11 | a = 100; 12 | // b = 200; // error 13 | print(a, b); 14 | // 100, 20 15 | } 16 | 17 | // array of const variable 18 | { 19 | const int a[5] = { 1, 2, 3, 4, 5 }; 20 | 21 | // a[1] = 10; // error 22 | 23 | print(a[0], a[1], a[2], a[3], a[4]); 24 | } 25 | 26 | // pointer of const variable 27 | { 28 | const int a = 10; 29 | print(a); 30 | 31 | const int* p = &a; 32 | p = 9; // valid 33 | // *p = 100; // error 34 | print(p, *p, a); 35 | } 36 | 37 | // string 38 | { 39 | const char* s = "hello"; 40 | 41 | print_str(s); 42 | // s[0] = 'H'; // error 43 | } 44 | 45 | return 0; 46 | } -------------------------------------------------------------------------------- /samples/define.c: -------------------------------------------------------------------------------- 1 | #define MY_MACRO 10 2 | #define MY_ADD(x, y) y + x * 10 3 | #define MY_ADD2(x, y) (y) + (x) * 10 4 | 5 | #if MY_MACRO == 10 6 | 7 | int main() 8 | { 9 | print(MY_ADD(MY_MACRO + 1, 20)); // print( 20 + MY_MACRO + 1 * 10 ) = 40 10 | print(MY_ADD2(MY_MACRO + 1, 20)); // print( (20) + (MY_MACRO + 1) * 10 ) = 130 11 | return 0; 12 | } 13 | 14 | #endif -------------------------------------------------------------------------------- /samples/dowhile.c: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int i = 0; 4 | do 5 | { 6 | print(i); 7 | if (i == 3) 8 | { 9 | i += 2; 10 | continue; 11 | } 12 | if (i == 8) 13 | { 14 | break; 15 | } 16 | 17 | ++i; 18 | } while (i < 10); 19 | 20 | // this will print 0, 1, 2, 3, 5, 6, 7, 8 21 | 22 | return 0; 23 | } -------------------------------------------------------------------------------- /samples/fib.c: -------------------------------------------------------------------------------- 1 | int fib(int); 2 | 3 | int main() 4 | { 5 | int i = 0; 6 | for (i = 1; i <= 20; ++i) 7 | { 8 | print(fib(i)); 9 | } 10 | 11 | return 0; 12 | } 13 | int fib(int n) 14 | { 15 | if (n <= 2) 16 | { 17 | return 1; 18 | } 19 | 20 | return fib(n - 1) + fib(n - 2); 21 | } -------------------------------------------------------------------------------- /samples/for.c: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int i; 4 | 5 | for (i = 1; i <= 5; i++) 6 | { 7 | if (i == 3) 8 | { 9 | continue; 10 | } 11 | print(i); 12 | 13 | if (i == 4) 14 | { 15 | break; 16 | } 17 | } 18 | // this will print 1, 2, 4 19 | 20 | print(100); 21 | return 0; 22 | } -------------------------------------------------------------------------------- /samples/for2.c: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int i; 4 | int j; 5 | int k; 6 | 7 | for (i = 1; i <= 5; ++i) 8 | { 9 | for (j = 1; j <= 5; ++j) 10 | { 11 | for (k = 1; k <= 5; ++k) 12 | { 13 | print(i, j, k); 14 | } 15 | } 16 | } 17 | return 0; 18 | } -------------------------------------------------------------------------------- /samples/logical.c: -------------------------------------------------------------------------------- 1 | int eval_true() 2 | { 3 | print(10); 4 | return 1; 5 | } 6 | int eval_false() 7 | { 8 | print(20); 9 | return 0; 10 | } 11 | 12 | int main() 13 | { 14 | // only 'eval_false' called 15 | print(eval_false() && eval_true()); 16 | // both 'eval_true' called 17 | print(eval_true() || eval_false()); 18 | 19 | print(1 == 1); 20 | print(1 != 0); 21 | print(0 < 1); 22 | print(1 > 0.0); 23 | print(0.0 <= 0.1); 24 | print(0.1 >= 0.0); 25 | 26 | return 0; 27 | } -------------------------------------------------------------------------------- /samples/pointer.c: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int a = 10; 4 | print(&a); // this will print stack index 5 | print(a); 6 | 7 | int* aptr = &a; 8 | print(aptr); 9 | print(*aptr); 10 | 11 | *aptr = 20; 12 | print(aptr); 13 | print(*aptr); 14 | print(a); 15 | 16 | print(&aptr); 17 | 18 | return 0; 19 | } -------------------------------------------------------------------------------- /samples/sample.c: -------------------------------------------------------------------------------- 1 | // declaration of function fibonacci sequence 2 | int fibonacci(int); 3 | 4 | #define MY_MACRO_FUNC(x, y) y + x 5 | 6 | #if MY_MACRO_FUNC(1, 2) == 3 7 | 8 | // main function 9 | int main() 10 | { 11 | print_str("Hello, World!"); // built in function 'print_str' 12 | int var = 10; 13 | int* ptr = &var; 14 | *ptr = MY_MACRO_FUNC(40, 60); 15 | print(ptr, *ptr, var); // built in function 'print' 16 | 17 | print(MY_MACRO_FUNC(10, 20)); 18 | 19 | // print fibonacci sequence 20 | print_str("Fibonacci sequence:"); 21 | int i; 22 | for (i = 1; i <= 10; i++) 23 | { 24 | print(i, fibonacci(i)); 25 | } 26 | 27 | return 0; 28 | } 29 | 30 | // definition of function fibonacci sequence using recursion 31 | int fibonacci(int n) 32 | { 33 | if (n <= 2) 34 | return 1; 35 | else 36 | return fibonacci(n - 1) + fibonacci(n - 2); 37 | } 38 | 39 | #else 40 | 41 | THIS WILL BE IGNORED 42 | 43 | #endif -------------------------------------------------------------------------------- /samples/string.c: -------------------------------------------------------------------------------- 1 | int strlen(char* s) 2 | { 3 | int len = 0; 4 | while (*s != 0) 5 | { 6 | ++s; 7 | ++len; 8 | } 9 | return len; 10 | } 11 | int main() 12 | { 13 | char* s = "Hello, World!"; 14 | 15 | print(strlen(s)); 16 | 17 | print_str(s); // built-in function 18 | 19 | return 0; 20 | } -------------------------------------------------------------------------------- /samples/struct.c: -------------------------------------------------------------------------------- 1 | struct MyStruct 2 | { 3 | int a; 4 | int b; 5 | int c; 6 | }; 7 | int main() 8 | { 9 | struct MyStruct s = { 1, 2, 3 }; 10 | 11 | int x = { 10 }; 12 | 13 | s.a = 10; 14 | print(&s.a); 15 | print(s.a); 16 | print(s.b); 17 | print(s.c); 18 | 19 | ++s.c; 20 | print(s.a); 21 | print(s.b); 22 | print(s.c); 23 | 24 | print(x); 25 | x = 20; 26 | print(x); 27 | 28 | struct MyStruct* sptr = &s; 29 | sptr->b = 100; 30 | print(s.b); 31 | 32 | struct MyStruct s2 = s; 33 | print(s2.a); 34 | print(s2.b); 35 | print(s2.c); 36 | s2.a = 100; 37 | s2.b = 200; 38 | s2.c = 300; 39 | 40 | print(s2.a); 41 | print(s2.b); 42 | print(s2.c); 43 | print(s.a); 44 | print(s.b); 45 | print(s.c); 46 | 47 | return 0; 48 | } -------------------------------------------------------------------------------- /samples/switch.c: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int a = 1; 4 | switch (a) 5 | { 6 | case 0: 7 | { 8 | print(0); 9 | break; 10 | } 11 | case 1: 12 | { 13 | print(1); 14 | } 15 | case 2: 16 | { 17 | print(2); 18 | break; 19 | } 20 | default: 21 | { 22 | print(3); 23 | break; 24 | } 25 | } 26 | // 1, 2 will be printed 27 | 28 | switch (a) 29 | { 30 | case 2: 31 | { 32 | print(2); 33 | break; 34 | } 35 | case 1: 36 | { 37 | print(1); 38 | break; 39 | } 40 | case 0: 41 | { 42 | print(0); 43 | break; 44 | } 45 | } 46 | // 1 will printed 47 | 48 | switch (a) 49 | { 50 | case 0: 51 | { 52 | print(0); 53 | break; 54 | } 55 | default: 56 | { 57 | print(1); 58 | } 59 | case 2: 60 | { 61 | print(2); 62 | } 63 | case 3: 64 | { 65 | print(3); 66 | break; 67 | } 68 | } 69 | // 1, 2, 3 will be printed 70 | 71 | return 0; 72 | } -------------------------------------------------------------------------------- /samples/typedef.c: -------------------------------------------------------------------------------- 1 | typedef int* int_ptr; 2 | typedef int** int_ptrptr; 3 | int main() 4 | { 5 | int val[2] = { 10, 20 }; 6 | 7 | int_ptr ptr = val; 8 | int_ptr ptr2 = val + 1; 9 | print(*ptr, *ptr2); 10 | // 10, 20 11 | 12 | int_ptrptr ptrptr = &ptr; 13 | // set val[0] to 100 14 | **ptrptr = 100; 15 | ptrptr = &ptr2; 16 | **ptrptr = 200; 17 | 18 | print(val[0], val[1]); 19 | 20 | return 0; 21 | } -------------------------------------------------------------------------------- /samples/while.c: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int i = 0; 4 | while (i < 10) 5 | { 6 | if (i == 6) 7 | { 8 | break; 9 | } 10 | print(i); 11 | if (i == 3) 12 | { 13 | i += 2; 14 | continue; 15 | } 16 | ++i; 17 | } 18 | // this will print 0, 1, 2, 3, 5 19 | 20 | return 0; 21 | } -------------------------------------------------------------------------------- /src/ast/declarator.rs: -------------------------------------------------------------------------------- 1 | use super::expression::Expression; 2 | use super::typename::TypeInfo; 3 | 4 | use std::vec::Vec; 5 | 6 | #[derive(Debug, Clone)] 7 | pub enum Declarator { 8 | Identifier(DeclIdentifier), 9 | DirectArrayFixed(DeclDirectArrayFixed), 10 | DirectArrayUnbounded(DeclDirectArrayUnbounded), 11 | DirectFunction(DeclDirectFunction), 12 | Const(DeclConst), 13 | Pointer(DeclPointer), 14 | Init(DeclInit), 15 | AbstractArrayFixed(DeclAbstractArrayFixed), 16 | AbstractArrayUnbounded(DeclAbstractArrayUnbounded), 17 | AbstractFunction(DeclAbstractFunction), 18 | AbstractPointer(DeclAbstractPointer), 19 | AbstractConst(DeclAbstractConst), 20 | } 21 | 22 | impl Declarator { 23 | pub fn resolve_typeinfo(&self, info: TypeInfo) -> (Option, TypeInfo) { 24 | match self { 25 | Declarator::Identifier(decl) => decl.resolve_typeinfo(info), 26 | Declarator::DirectArrayFixed(decl) => decl.resolve_typeinfo(info), 27 | Declarator::DirectArrayUnbounded(decl) => decl.resolve_typeinfo(info), 28 | Declarator::DirectFunction(decl) => decl.resolve_typeinfo(info), 29 | Declarator::Const(decl) => decl.resolve_typeinfo(info), 30 | Declarator::Pointer(decl) => decl.resolve_typeinfo(info), 31 | Declarator::Init(decl) => decl.resolve_typeinfo(info), 32 | Declarator::AbstractArrayFixed(decl) => decl.resolve_typeinfo(info), 33 | Declarator::AbstractArrayUnbounded(decl) => decl.resolve_typeinfo(info), 34 | Declarator::AbstractFunction(decl) => decl.resolve_typeinfo(info), 35 | Declarator::AbstractPointer(decl) => decl.resolve_typeinfo(info), 36 | Declarator::AbstractConst(decl) => decl.resolve_typeinfo(info), 37 | } 38 | } 39 | } 40 | 41 | #[derive(Debug, Clone)] 42 | pub struct DeclIdentifier { 43 | pub name: String, 44 | } 45 | impl DeclIdentifier { 46 | pub fn resolve_typeinfo(&self, info: TypeInfo) -> (Option, TypeInfo) { 47 | (Some(self.name.clone()), info) 48 | } 49 | } 50 | 51 | #[derive(Debug, Clone)] 52 | pub struct DeclDirectArrayFixed { 53 | pub declarator: Box, 54 | pub size: Expression, 55 | } 56 | impl DeclDirectArrayFixed { 57 | pub fn resolve_typeinfo(&self, info: TypeInfo) -> (Option, TypeInfo) { 58 | let (name, info) = self.declarator.resolve_typeinfo(info); 59 | let size = self 60 | .size 61 | .get_constant_i64() 62 | .expect("Array size must be constant") as usize; 63 | (name, TypeInfo::Array(Box::new(info), Some(size))) 64 | } 65 | } 66 | 67 | #[derive(Debug, Clone)] 68 | pub struct DeclDirectArrayUnbounded { 69 | pub declarator: Box, 70 | } 71 | impl DeclDirectArrayUnbounded { 72 | pub fn resolve_typeinfo(&self, info: TypeInfo) -> (Option, TypeInfo) { 73 | let (name, info) = self.declarator.resolve_typeinfo(info); 74 | (name, TypeInfo::Array(Box::new(info), None)) 75 | } 76 | } 77 | 78 | #[derive(Debug, Clone)] 79 | pub struct DeclDirectFunction { 80 | pub declarator: Box, 81 | pub params: Vec<(Option, TypeInfo)>, 82 | } 83 | impl DeclDirectFunction { 84 | pub fn resolve_typeinfo(&self, info: TypeInfo) -> (Option, TypeInfo) { 85 | let (name, return_type) = self.declarator.resolve_typeinfo(info); 86 | let mut params = Vec::new(); 87 | for (_, param_type) in &self.params { 88 | params.push(param_type.clone()); 89 | } 90 | (name, TypeInfo::Function(Box::new(return_type), params)) 91 | } 92 | } 93 | #[derive(Debug, Clone)] 94 | pub struct DeclConst { 95 | pub declarator: Box, 96 | } 97 | impl DeclConst { 98 | pub fn resolve_typeinfo(&self, info: TypeInfo) -> (Option, TypeInfo) { 99 | let (name, info) = self.declarator.resolve_typeinfo(info); 100 | (name, TypeInfo::Const(Box::new(info))) 101 | } 102 | } 103 | 104 | #[derive(Debug, Clone)] 105 | pub struct DeclPointer { 106 | pub declarator: Box, 107 | } 108 | impl DeclPointer { 109 | pub fn resolve_typeinfo(&self, info: TypeInfo) -> (Option, TypeInfo) { 110 | let (name, info) = self.declarator.resolve_typeinfo(info); 111 | (name, TypeInfo::Pointer(Box::new(info))) 112 | } 113 | } 114 | 115 | #[derive(Debug, Clone)] 116 | pub struct DeclInit { 117 | pub declarator: Box, 118 | pub initializer: Option, 119 | } 120 | impl DeclInit { 121 | pub fn resolve_typeinfo(&self, info: TypeInfo) -> (Option, TypeInfo) { 122 | self.declarator.resolve_typeinfo(info) 123 | } 124 | } 125 | 126 | #[derive(Debug, Clone)] 127 | pub struct DeclAbstractArrayFixed { 128 | pub declarator: Option>, 129 | pub size: Expression, 130 | } 131 | impl DeclAbstractArrayFixed { 132 | pub fn resolve_typeinfo(&self, info: TypeInfo) -> (Option, TypeInfo) { 133 | let (name, info_) = if let Some(decl) = &self.declarator { 134 | decl.resolve_typeinfo(info) 135 | } else { 136 | (None, info) 137 | }; 138 | let size = self 139 | .size 140 | .get_constant_i64() 141 | .expect("Array size must be constant") as usize; 142 | (name, TypeInfo::Array(Box::new(info_), Some(size))) 143 | } 144 | } 145 | 146 | #[derive(Debug, Clone)] 147 | pub struct DeclAbstractArrayUnbounded { 148 | pub declarator: Option>, 149 | } 150 | impl DeclAbstractArrayUnbounded { 151 | pub fn resolve_typeinfo(&self, info: TypeInfo) -> (Option, TypeInfo) { 152 | let (name, info_) = if let Some(decl) = &self.declarator { 153 | decl.resolve_typeinfo(info) 154 | } else { 155 | (None, info) 156 | }; 157 | (name, TypeInfo::Array(Box::new(info_), None)) 158 | } 159 | } 160 | 161 | #[derive(Debug, Clone)] 162 | pub struct DeclAbstractFunction { 163 | pub declarator: Option>, 164 | pub params: Vec<(Option, TypeInfo)>, 165 | } 166 | impl DeclAbstractFunction { 167 | pub fn resolve_typeinfo(&self, info: TypeInfo) -> (Option, TypeInfo) { 168 | let (name, return_type) = if let Some(decl) = &self.declarator { 169 | decl.resolve_typeinfo(info) 170 | } else { 171 | (None, info) 172 | }; 173 | ( 174 | name, 175 | TypeInfo::Function( 176 | Box::new(return_type), 177 | self.params.iter().map(|(_, t)| t.clone()).collect(), 178 | ), 179 | ) 180 | } 181 | } 182 | 183 | #[derive(Debug, Clone)] 184 | pub struct DeclAbstractPointer { 185 | pub declarator: Option>, 186 | } 187 | impl DeclAbstractPointer { 188 | pub fn resolve_typeinfo(&self, info: TypeInfo) -> (Option, TypeInfo) { 189 | let (name, info_) = if let Some(decl) = &self.declarator { 190 | decl.resolve_typeinfo(info) 191 | } else { 192 | (None, info) 193 | }; 194 | (name, TypeInfo::Pointer(Box::new(info_))) 195 | } 196 | } 197 | 198 | #[derive(Debug, Clone)] 199 | pub struct DeclAbstractConst { 200 | pub declarator: Option>, 201 | } 202 | impl DeclAbstractConst { 203 | pub fn resolve_typeinfo(&self, info: TypeInfo) -> (Option, TypeInfo) { 204 | let (name, info_) = if let Some(decl) = &self.declarator { 205 | decl.resolve_typeinfo(info) 206 | } else { 207 | (None, info) 208 | }; 209 | (name, TypeInfo::Const(Box::new(info_))) 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /src/ast/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod declarator; 2 | pub mod expression; 3 | pub mod parser; 4 | pub mod statement; 5 | pub mod typename; 6 | -------------------------------------------------------------------------------- /src/ast/statement.rs: -------------------------------------------------------------------------------- 1 | use super::{expression::Expression, typename::TypeInfo}; 2 | use crate::virtualmachine::instruction::generation::FunctionInfo; 3 | use crate::virtualmachine::instruction::generation::InstructionGenerator; 4 | use crate::virtualmachine::instruction::operand::Operand; 5 | use crate::virtualmachine::instruction::*; 6 | use crate::virtualmachine::program::STACK_POINTER_BASE_REGISTER; 7 | use crate::virtualmachine::program::STACK_POINTER_REGISTER; 8 | use crate::virtualmachine::scope::FunctionScope; 9 | use crate::virtualmachine::variable::VariableData; 10 | 11 | #[derive(Debug, Clone)] 12 | pub enum Statement { 13 | Null(StmtNull), 14 | Expression(StmtExpression), 15 | Labeled(StmtLabeled), 16 | Compound(StmtCompound), 17 | If(StmtIf), 18 | Switch(StmtSwitch), 19 | Case(StmtCase), 20 | Default(StmtDefault), 21 | Continue(StmtContinue), 22 | Break(StmtBreak), 23 | While(StmtWhile), 24 | DoWhile(StmtDoWhile), 25 | For(StmtFor), 26 | Goto(StmtGoto), 27 | Return(StmtReturn), 28 | StructDefinition(StmtStructDefinition), 29 | FunctionDeclaration(StmtFunctionDeclaration), 30 | Declaration(StmtDeclaration), 31 | Typedef(StmtTypedef), 32 | FunctionDefinition(StmtFunctionDefinition), 33 | TranslationUnit(TranslationUnit), 34 | } 35 | 36 | impl Statement { 37 | pub fn emit(&self, instructions: &mut InstructionGenerator) { 38 | match self { 39 | Statement::Null(stmt) => stmt.emit(instructions), 40 | Statement::Expression(stmt) => stmt.emit(instructions), 41 | Statement::Labeled(stmt) => stmt.emit(instructions), 42 | Statement::Compound(stmt) => stmt.emit(instructions), 43 | Statement::If(stmt) => stmt.emit(instructions), 44 | Statement::Switch(stmt) => stmt.emit(instructions), 45 | Statement::Case(stmt) => stmt.emit(instructions), 46 | Statement::Default(stmt) => stmt.emit(instructions), 47 | Statement::Continue(stmt) => stmt.emit(instructions), 48 | Statement::Break(stmt) => stmt.emit(instructions), 49 | Statement::While(stmt) => stmt.emit(instructions), 50 | Statement::DoWhile(stmt) => stmt.emit(instructions), 51 | Statement::For(stmt) => stmt.emit(instructions), 52 | Statement::Goto(stmt) => stmt.emit(instructions), 53 | Statement::Return(stmt) => stmt.emit(instructions), 54 | Statement::StructDefinition(stmt) => stmt.emit(instructions), 55 | Statement::FunctionDeclaration(stmt) => stmt.emit(instructions), 56 | Statement::Declaration(stmt) => stmt.emit(instructions), 57 | Statement::Typedef(stmt) => stmt.emit(instructions), 58 | Statement::FunctionDefinition(stmt) => stmt.emit(instructions), 59 | Statement::TranslationUnit(stmt) => stmt.emit(instructions), 60 | } 61 | } 62 | } 63 | 64 | /// Statements that do nothing 65 | #[derive(Debug, Clone)] 66 | pub struct StmtNull; 67 | impl StmtNull { 68 | pub fn emit(&self, _instructions: &mut InstructionGenerator) {} 69 | } 70 | 71 | /// for any expression ends with semicolon ';' 72 | #[derive(Debug, Clone)] 73 | pub struct StmtExpression { 74 | pub expression: Expression, 75 | } 76 | impl StmtExpression { 77 | pub fn emit(&self, instructions: &mut InstructionGenerator) { 78 | self.expression.emit(instructions); 79 | } 80 | } 81 | 82 | /// label: 83 | /// statement 84 | #[derive(Debug, Clone)] 85 | pub struct StmtLabeled { 86 | pub label: String, 87 | pub statement: Box, 88 | } 89 | impl StmtLabeled { 90 | pub fn emit(&self, instructions: &mut InstructionGenerator) { 91 | instructions.set_label(&self.label); 92 | self.statement.emit(instructions); 93 | } 94 | } 95 | 96 | /// { statements ... } 97 | #[derive(Debug, Clone)] 98 | pub struct StmtCompound { 99 | pub statements: Vec, 100 | } 101 | impl StmtCompound { 102 | pub fn emit(&self, instructions: &mut InstructionGenerator) { 103 | instructions.push_scope(); 104 | 105 | for statement in &self.statements { 106 | statement.emit(instructions); 107 | } 108 | 109 | instructions.pop_scope(); 110 | } 111 | } 112 | 113 | /// if ( condition_expression ) then_statement else else_statement 114 | /// no else if statement 115 | #[derive(Debug, Clone)] 116 | pub struct StmtIf { 117 | pub cond: Expression, 118 | pub then_statement: Box, 119 | pub else_statement: Option>, 120 | } 121 | impl StmtIf { 122 | pub fn emit(&self, instructions: &mut InstructionGenerator) { 123 | let else_label = instructions.get_unique_label(); 124 | let end_label = instructions.get_unique_label(); 125 | 126 | self.cond.emit(instructions); 127 | instructions.push(Instruction::JumpZero(JumpZero { 128 | label: else_label.clone(), 129 | operand_cond: Operand::Register(0), 130 | })); 131 | self.then_statement.emit(instructions); 132 | instructions.push(Instruction::Jump(Jump { 133 | label: end_label.clone(), 134 | })); 135 | instructions.set_label(&else_label); 136 | if let Some(else_statement) = &self.else_statement { 137 | else_statement.emit(instructions); 138 | } 139 | instructions.set_label(&end_label); 140 | } 141 | } 142 | 143 | /// switch ( target_expression ) body_statement 144 | #[derive(Debug, Clone)] 145 | pub struct StmtSwitch { 146 | pub target: Expression, 147 | pub statement: Box, 148 | } 149 | impl StmtSwitch { 150 | pub fn emit(&self, instructions: &mut InstructionGenerator) { 151 | let end_label = instructions.get_unique_label(); 152 | let default_label = instructions.get_unique_label(); 153 | instructions 154 | .label_stack 155 | .push((default_label.clone(), end_label.clone())); 156 | 157 | // push target to stack 158 | self.target.emit(instructions); 159 | if self.target.is_return_reference(instructions) { 160 | instructions.push(Instruction::PushStack(PushStack { 161 | operand: Operand::Derefed(0, 0), 162 | })); 163 | } else { 164 | instructions.push(Instruction::PushStack(PushStack { 165 | operand: Operand::Register(0), 166 | })); 167 | } 168 | // and push variable for 'if the pattern matched already?' 169 | instructions.push(Instruction::PushStack(PushStack { 170 | operand: Operand::Value(VariableData::UInt8(0)), 171 | })); 172 | 173 | // body 174 | self.statement.emit(instructions); 175 | // check if the pattern matched and default is defined 176 | if instructions.labels.get(&default_label).is_some() { 177 | // if not matched, set pattern matched to true and goto default 178 | instructions.push(Instruction::MoveRegister(MoveRegister { 179 | operand_from: Operand::Derefed(STACK_POINTER_REGISTER, -1), 180 | operand_to: Operand::Register(0), 181 | })); 182 | instructions.push(Instruction::JumpZero(JumpZero { 183 | label: default_label.clone(), 184 | operand_cond: Operand::Register(0), 185 | })); 186 | } 187 | 188 | // end label here, cleanup 189 | instructions.set_label(&end_label); 190 | // pop pattern-matched state and target from stack 191 | instructions.push(Instruction::SubAssign(SubAssign { 192 | lhs: Operand::Register(STACK_POINTER_REGISTER), 193 | rhs: Operand::Value(VariableData::UInt64(2)), 194 | })); 195 | 196 | instructions 197 | .label_stack 198 | .pop() 199 | .expect("Switch: label_stack is empty"); 200 | } 201 | } 202 | /// case value: statement 203 | #[derive(Debug, Clone)] 204 | pub struct StmtCase { 205 | pub value: Expression, 206 | pub statement: Box, 207 | } 208 | impl StmtCase { 209 | pub fn emit(&self, instructions: &mut InstructionGenerator) { 210 | let case_end_label = instructions.get_unique_label(); 211 | let comparison_skip_label = instructions.get_unique_label(); 212 | 213 | // copy state from stack 214 | instructions.push(Instruction::MoveRegister(MoveRegister { 215 | operand_from: Operand::Derefed(STACK_POINTER_REGISTER, -1), 216 | operand_to: Operand::Register(0), 217 | })); 218 | // if the pattern matched already, skip comparison 219 | instructions.push(Instruction::JumpNonZero(JumpNonZero { 220 | label: comparison_skip_label.clone(), 221 | operand_cond: Operand::Register(0), 222 | })); 223 | 224 | // comparison start here 225 | // evaluate value 226 | self.value.emit(instructions); 227 | // register1 = value 228 | if self.value.is_return_reference(instructions) { 229 | instructions.push(Instruction::MoveRegister(MoveRegister { 230 | operand_from: Operand::Derefed(0, 0), 231 | operand_to: Operand::Register(1), 232 | })); 233 | } else { 234 | instructions.push(Instruction::MoveRegister(MoveRegister { 235 | operand_from: Operand::Register(0), 236 | operand_to: Operand::Register(1), 237 | })); 238 | } 239 | // register0 = target 240 | instructions.push(Instruction::MoveRegister(MoveRegister { 241 | operand_from: Operand::Derefed(STACK_POINTER_REGISTER, -2), 242 | operand_to: Operand::Register(0), 243 | })); 244 | // register2 = result of comparison 245 | instructions.push(Instruction::Equal(Equal { 246 | lhs: Operand::Register(0), 247 | rhs: Operand::Register(1), 248 | to: Operand::Register(2), 249 | })); 250 | instructions.push(Instruction::JumpZero(JumpZero { 251 | label: case_end_label.clone(), 252 | operand_cond: Operand::Register(2), 253 | })); 254 | 255 | instructions.push(Instruction::MoveRegister(MoveRegister { 256 | operand_from: Operand::Value(VariableData::UInt8(1)), 257 | operand_to: Operand::Derefed(STACK_POINTER_REGISTER, -1), 258 | })); 259 | 260 | instructions.set_label(&comparison_skip_label); 261 | self.statement.emit(instructions); 262 | 263 | instructions.set_label(&case_end_label); 264 | } 265 | } 266 | 267 | /// default: statement 268 | #[derive(Debug, Clone)] 269 | pub struct StmtDefault { 270 | pub statement: Box, 271 | } 272 | impl StmtDefault { 273 | pub fn emit(&self, instructions: &mut InstructionGenerator) { 274 | let default_end_label = instructions.get_unique_label(); 275 | let (default_label, _) = instructions 276 | .label_stack 277 | .last() 278 | .expect("Default: label_stack is empty") 279 | .clone(); 280 | // skip default statement 281 | instructions.push(Instruction::Jump(Jump { 282 | label: default_end_label.clone(), 283 | })); 284 | instructions.set_label(&default_label); 285 | // set pattern matched 286 | instructions.push(Instruction::MoveRegister(MoveRegister { 287 | operand_from: Operand::Value(VariableData::UInt8(1)), 288 | operand_to: Operand::Derefed(STACK_POINTER_REGISTER, -1), 289 | })); 290 | self.statement.emit(instructions); 291 | instructions.set_label(&default_end_label); 292 | } 293 | } 294 | 295 | /// continue; 296 | #[derive(Debug, Clone)] 297 | pub struct StmtContinue; 298 | impl StmtContinue { 299 | pub fn emit(&self, instructions: &mut InstructionGenerator) { 300 | let continue_label = &instructions 301 | .label_stack 302 | .last() 303 | .expect("Continue: label_stack is empty") 304 | .0; 305 | instructions.push(Instruction::Jump(Jump { 306 | label: continue_label.clone(), 307 | })); 308 | } 309 | } 310 | 311 | /// break; 312 | #[derive(Debug, Clone)] 313 | pub struct StmtBreak; 314 | impl StmtBreak { 315 | pub fn emit(&self, instructions: &mut InstructionGenerator) { 316 | let end_label = &instructions 317 | .label_stack 318 | .last() 319 | .expect("Break: label_stack is empty") 320 | .1; 321 | instructions.push(Instruction::Jump(Jump { 322 | label: end_label.clone(), 323 | })); 324 | } 325 | } 326 | 327 | /// while ( condition_expression ) statement 328 | #[derive(Debug, Clone)] 329 | pub struct StmtWhile { 330 | pub cond: Expression, 331 | pub statement: Box, 332 | } 333 | impl StmtWhile { 334 | fn emit(&self, instructions: &mut InstructionGenerator) { 335 | let start_label = instructions.get_unique_label(); 336 | let end_label = instructions.get_unique_label(); 337 | instructions 338 | .label_stack 339 | .push((start_label.clone(), end_label.clone())); 340 | 341 | instructions.set_label(&start_label); 342 | self.cond.emit(instructions); 343 | if self.cond.is_return_reference(instructions) { 344 | instructions.push(Instruction::JumpZero(JumpZero { 345 | label: end_label.clone(), 346 | operand_cond: Operand::Derefed(0, 0), 347 | })); 348 | } else { 349 | instructions.push(Instruction::JumpZero(JumpZero { 350 | label: end_label.clone(), 351 | operand_cond: Operand::Register(0), 352 | })); 353 | } 354 | self.statement.emit(instructions); 355 | instructions.push(Instruction::Jump(Jump { 356 | label: start_label.clone(), 357 | })); 358 | instructions.set_label(&end_label); 359 | 360 | instructions 361 | .label_stack 362 | .pop() 363 | .expect("While: label_stack is empty"); 364 | } 365 | } 366 | 367 | /// do statement while ( condition_expression ); 368 | 369 | #[derive(Debug, Clone)] 370 | pub struct StmtDoWhile { 371 | pub cond: Expression, 372 | pub statement: Box, 373 | } 374 | impl StmtDoWhile { 375 | pub fn emit(&self, instructions: &mut InstructionGenerator) { 376 | let start_label = instructions.get_unique_label(); 377 | let continue_label = instructions.get_unique_label(); 378 | let end_label = instructions.get_unique_label(); 379 | 380 | instructions 381 | .label_stack 382 | .push((continue_label.clone(), end_label.clone())); 383 | 384 | // start_label: 385 | // do { body ... } 386 | // continue_label: 387 | // while (cond); 388 | // end_label: 389 | 390 | instructions.set_label(&start_label); 391 | self.statement.emit(instructions); 392 | 393 | instructions.set_label(&continue_label); 394 | self.cond.emit(instructions); 395 | if self.cond.is_return_reference(instructions) { 396 | instructions.push(Instruction::JumpNonZero(JumpNonZero { 397 | label: start_label.clone(), 398 | operand_cond: Operand::Derefed(0, 0), 399 | })); 400 | } else { 401 | instructions.push(Instruction::JumpNonZero(JumpNonZero { 402 | label: start_label.clone(), 403 | operand_cond: Operand::Register(0), 404 | })); 405 | } 406 | instructions.set_label(&end_label); 407 | 408 | instructions 409 | .label_stack 410 | .pop() 411 | .expect("DoWhile: label_stack is empty"); 412 | } 413 | } 414 | 415 | /// for ( init; cond; next ) statement 416 | /// since init is expression, must declare variable before entering for loop 417 | #[derive(Debug, Clone)] 418 | pub struct StmtFor { 419 | pub init: Expression, 420 | pub cond: Expression, 421 | pub next: Option, 422 | pub statement: Box, 423 | } 424 | impl StmtFor { 425 | pub fn emit(&self, instructions: &mut InstructionGenerator) { 426 | let cond_label = instructions.get_unique_label(); 427 | let end_label = instructions.get_unique_label(); 428 | let continue_label = instructions.get_unique_label(); 429 | instructions 430 | .label_stack 431 | .push((continue_label.clone(), end_label.clone())); 432 | 433 | // init 434 | // COND: 435 | // cond 436 | // body 437 | // CONTINUE: 438 | // next 439 | // jump COND 440 | // END: 441 | 442 | self.init.emit(instructions); 443 | instructions.set_label(&cond_label); 444 | self.cond.emit(instructions); 445 | if self.cond.is_return_reference(instructions) { 446 | instructions.push(Instruction::JumpZero(JumpZero { 447 | label: end_label.clone(), 448 | operand_cond: Operand::Derefed(0, 0), 449 | })); 450 | } else { 451 | instructions.push(Instruction::JumpZero(JumpZero { 452 | label: end_label.clone(), 453 | operand_cond: Operand::Register(0), 454 | })); 455 | } 456 | self.statement.emit(instructions); 457 | instructions.set_label(&continue_label); 458 | if let Some(next) = &self.next { 459 | next.emit(instructions); 460 | } 461 | instructions.push(Instruction::Jump(Jump { 462 | label: cond_label.clone(), 463 | })); 464 | instructions.set_label(&end_label); 465 | 466 | instructions 467 | .label_stack 468 | .pop() 469 | .expect("For: label_stack is empty"); 470 | } 471 | } 472 | 473 | /// goto label; 474 | #[derive(Debug, Clone)] 475 | pub struct StmtGoto { 476 | pub label: String, 477 | } 478 | impl StmtGoto { 479 | pub fn emit(&self, instructions: &mut InstructionGenerator) { 480 | instructions.push(Instruction::Jump(Jump { 481 | label: self.label.clone(), 482 | })); 483 | } 484 | } 485 | 486 | /// return; or return expression; 487 | #[derive(Debug, Clone)] 488 | pub struct StmtReturn { 489 | pub expr: Option, 490 | } 491 | impl StmtReturn { 492 | pub fn emit(&self, instructions: &mut InstructionGenerator) { 493 | if let Some(expr) = &self.expr { 494 | expr.emit(instructions); 495 | // force return as value 496 | if expr.is_return_reference(instructions) { 497 | instructions.push(Instruction::MoveRegister(MoveRegister { 498 | operand_from: Operand::Derefed(0, 0), 499 | operand_to: Operand::Register(0), 500 | })); 501 | } 502 | } 503 | instructions.push(Instruction::Return(Return {})); 504 | } 505 | } 506 | 507 | /// type definition of struct, union, enum 508 | #[derive(Debug, Clone)] 509 | pub struct StmtStructDefinition { 510 | pub typeinfo: TypeInfo, 511 | } 512 | impl StmtStructDefinition { 513 | pub fn emit(&self, instructions: &mut InstructionGenerator) { 514 | match &self.typeinfo { 515 | TypeInfo::Struct(t) => { 516 | if t.name.is_none() { 517 | println!("Anonymous struct in declaration statement; ignored it"); 518 | } else { 519 | let old = if instructions.scopes.is_empty() { 520 | &mut instructions.global_scope 521 | } else { 522 | instructions.scopes.last_mut().unwrap() 523 | } 524 | .type_infos 525 | .insert( 526 | t.name.as_ref().unwrap().clone(), 527 | TypeInfo::Struct(t.clone()), 528 | ); 529 | if old.is_some() { 530 | panic!("Struct {} already exists", t.name.as_ref().unwrap()); 531 | } 532 | } 533 | } 534 | _ => panic!("Invalid type for type declaration: {:?}", self.typeinfo), 535 | } 536 | } 537 | } 538 | 539 | /// return_type function_name ( params ); 540 | #[derive(Debug, Clone)] 541 | pub struct StmtFunctionDeclaration { 542 | pub return_type: TypeInfo, 543 | pub name: String, 544 | pub params: Vec, 545 | } 546 | impl StmtFunctionDeclaration { 547 | pub fn emit(&self, instructions: &mut InstructionGenerator) { 548 | // check if its already declared 549 | let old = instructions.functions.get(&self.name); 550 | if let Some(old) = old { 551 | // no need to check if the function is already defined, 552 | // since this statement is declaration statement 553 | 554 | // check parameter types are same 555 | let param_equal = old 556 | .params 557 | .iter() 558 | .map(|(_, type_)| type_) 559 | .eq(self.params.iter()); 560 | if param_equal == false { 561 | panic!( 562 | "Function {} is already declared with different parameter types", 563 | &self.name 564 | ); 565 | } 566 | 567 | // check return type is same 568 | if &old.return_type != &self.return_type { 569 | panic!( 570 | "Function {} is already declared with different return type", 571 | &self.name 572 | ); 573 | } 574 | } else { 575 | // function is not declared 576 | let params: Vec<_> = self 577 | .params 578 | .iter() 579 | .map(|typeinfo| (None, typeinfo.clone())) 580 | .collect(); 581 | let function_data = FunctionInfo { 582 | return_type: self.return_type.clone(), 583 | params, 584 | is_defined: false, 585 | }; 586 | instructions 587 | .functions 588 | .insert(self.name.clone(), function_data); 589 | } 590 | } 591 | } 592 | 593 | /// typename var1, var2, var3, ...,; 594 | /// var_i can be decorated with qualifiers; pointer, const ... 595 | #[derive(Debug, Clone)] 596 | pub struct StmtDeclaration { 597 | pub vars: Vec<(String, TypeInfo, Option)>, // name, type, initializer 598 | } 599 | impl StmtDeclaration { 600 | pub fn emit(&self, instructions: &mut InstructionGenerator) { 601 | for declaration in &self.vars { 602 | // variable declaration 603 | if let Some(initial_value) = &declaration.2 { 604 | // variable with initial value 605 | 606 | let var_type = instructions.get_true_typeinfo(&declaration.1); 607 | // check type 608 | match var_type.remove_const() { 609 | TypeInfo::Function(_, _) => { 610 | panic!( 611 | "Function declaration cannot have initial value; something went wrong" 612 | ); 613 | } 614 | TypeInfo::Struct(sinfo) => { 615 | // link name to stack 616 | instructions.declare_variable( 617 | &declaration.0, 618 | &var_type, 619 | sinfo.number_of_primitives(), 620 | ); 621 | 622 | sinfo.emit_init(instructions, initial_value); 623 | } 624 | TypeInfo::Union(_uinfo) => { 625 | panic!("Union declaration in declaration statement is not implemented"); 626 | } 627 | 628 | // array 629 | TypeInfo::Array(type_, size) => { 630 | // initializer must be initializer list 631 | let initial_value = match initial_value { 632 | Expression::InitializerList(initial_value) => initial_value, 633 | _ => unreachable!("Array initializer must be initializer list"), 634 | }; 635 | 636 | let size = match size { 637 | Some(size) => { 638 | if initial_value.initializers.len() > size { 639 | panic!("Too many initializers for array"); 640 | } 641 | size 642 | } 643 | None => initial_value.initializers.len(), 644 | }; 645 | if size == 0 { 646 | panic!("Array size must be greater than 0"); 647 | } 648 | 649 | // link name to stack 650 | instructions.declare_variable( 651 | &declaration.0, 652 | &TypeInfo::Array(type_.clone(), Some(size)), 653 | size * type_.number_of_primitives(), 654 | ); 655 | 656 | TypeInfo::Array(type_.clone(), Some(size)) 657 | .emit_init(instructions, declaration.2.as_ref().unwrap()); 658 | } 659 | 660 | // primitive types + pointer 661 | TypeInfo::UInt8 662 | | TypeInfo::UInt16 663 | | TypeInfo::UInt32 664 | | TypeInfo::UInt64 665 | | TypeInfo::Int8 666 | | TypeInfo::Int16 667 | | TypeInfo::Int32 668 | | TypeInfo::Int64 669 | | TypeInfo::Float32 670 | | TypeInfo::Float64 671 | | TypeInfo::Pointer(_) => { 672 | // link name to stack 673 | instructions.declare_variable(&declaration.0, &var_type, 1); 674 | 675 | var_type.emit_init(instructions, initial_value); 676 | } 677 | _ => panic!( 678 | "Invalid type for variable declaration: {:?}", 679 | &declaration.1 680 | ), 681 | } 682 | } else { 683 | // variable without initial value 684 | 685 | let var_type = instructions.get_true_typeinfo(&declaration.1); 686 | match var_type.remove_const() { 687 | TypeInfo::Struct(sinfo) => { 688 | let size = sinfo.number_of_primitives(); 689 | if size == 0 { 690 | panic!("Struct size must be greater than 0"); 691 | } 692 | // link name to stack 693 | instructions.declare_variable(&declaration.0, &var_type, size); 694 | 695 | sinfo.emit_default(instructions); 696 | } 697 | TypeInfo::Union(_uinfo) => { 698 | panic!("Union declaration in declaration statement is not implemented"); 699 | } 700 | 701 | TypeInfo::Array(type_, size) => { 702 | let size = 703 | size.expect("Array declaration without initializer must have size"); 704 | if size == 0 { 705 | panic!("Array size must be greater than 0"); 706 | } 707 | 708 | // link name to stack 709 | instructions.declare_variable( 710 | &declaration.0, 711 | &TypeInfo::Array(type_.clone(), Some(size)), 712 | size * type_.number_of_primitives(), 713 | ); 714 | 715 | TypeInfo::Array(type_.clone(), Some(size)).emit_default(instructions); 716 | } 717 | 718 | // primitive types + pointer 719 | TypeInfo::UInt8 720 | | TypeInfo::UInt16 721 | | TypeInfo::UInt32 722 | | TypeInfo::UInt64 723 | | TypeInfo::Int8 724 | | TypeInfo::Int16 725 | | TypeInfo::Int32 726 | | TypeInfo::Int64 727 | | TypeInfo::Float32 728 | | TypeInfo::Float64 729 | | TypeInfo::Pointer(_) => { 730 | // link name to stack 731 | instructions.declare_variable(&declaration.0, &var_type, 1); 732 | 733 | // push default value to stack 734 | var_type.emit_default(instructions); 735 | } 736 | _ => panic!( 737 | "Invalid type for variable declaration: {:?}", 738 | &declaration.1 739 | ), 740 | } 741 | } 742 | } 743 | } 744 | } 745 | 746 | #[derive(Debug, Clone)] 747 | pub struct StmtTypedef { 748 | pub name: String, 749 | pub typeinfo: TypeInfo, 750 | } 751 | impl StmtTypedef { 752 | pub fn emit(&self, instructions: &mut InstructionGenerator) { 753 | let old = if instructions.scopes.is_empty() { 754 | &mut instructions.global_scope 755 | } else { 756 | instructions.scopes.last_mut().unwrap() 757 | } 758 | .type_infos 759 | .insert(self.name.clone(), self.typeinfo.clone()); 760 | if old.is_some() { 761 | panic!("Type {} already exists", self.name); 762 | } 763 | } 764 | } 765 | 766 | #[derive(Debug, Clone)] 767 | pub struct StmtFunctionDefinition { 768 | pub return_type: TypeInfo, 769 | pub name: String, 770 | pub params: Vec<(Option, TypeInfo)>, 771 | pub body: Box, 772 | } 773 | impl StmtFunctionDefinition { 774 | pub fn emit(&self, instructions: &mut InstructionGenerator) { 775 | if instructions.function_scope.is_some() { 776 | panic!("nested function is not allowed"); 777 | } 778 | 779 | let function_data = FunctionInfo { 780 | return_type: instructions.get_true_typeinfo(&self.return_type), 781 | params: self 782 | .params 783 | .iter() 784 | .map(|(name, type_)| (name.clone(), instructions.get_true_typeinfo(type_))) 785 | .collect(), 786 | is_defined: true, 787 | }; 788 | let old = instructions 789 | .functions 790 | .insert(self.name.clone(), function_data); 791 | if let Some(old) = old { 792 | // check if old was declaration 793 | if old.is_defined { 794 | panic!("redefinition of function {}", &self.name); 795 | } 796 | 797 | // check parameter types are same 798 | if old 799 | .params 800 | .iter() 801 | .map(|(_, type_)| instructions.get_true_typeinfo(type_)) 802 | .eq(self 803 | .params 804 | .iter() 805 | .map(|(_, type_)| instructions.get_true_typeinfo(type_))) 806 | == false 807 | { 808 | panic!( 809 | "Function {} is already declared with different parameter types", 810 | &self.name 811 | ); 812 | } 813 | 814 | // check return type is same 815 | if instructions.get_true_typeinfo(&old.return_type) 816 | != instructions.get_true_typeinfo(&self.return_type) 817 | { 818 | panic!( 819 | "Function {} is already declared with different return type", 820 | &self.name 821 | ); 822 | } 823 | } 824 | instructions.set_label(&self.name); 825 | 826 | instructions.function_scope = Some(FunctionScope::new()); 827 | instructions.push_scope(); 828 | 829 | // argument initialization 830 | // function's arguments are pushed to stack before call ( and MUST BE ) 831 | // ===== top of stack: return_address -> arg1 -> arg2 ... ===== 832 | // ^ top of stack 833 | 834 | for (id, param) in self.params.iter().enumerate() { 835 | if param.0.is_some() { 836 | instructions.link_variable( 837 | param.0.as_ref().unwrap(), 838 | &instructions.get_true_typeinfo(¶m.1), 839 | -(id as isize) - 3, 840 | ); 841 | } 842 | } 843 | 844 | // push base pointer 845 | instructions.push(Instruction::PushStack(PushStack { 846 | operand: Operand::Register(STACK_POINTER_BASE_REGISTER), 847 | })); 848 | // move base 849 | // rbp = rsp 850 | instructions.push(Instruction::MoveRegister(MoveRegister { 851 | operand_from: Operand::Register(STACK_POINTER_REGISTER), 852 | operand_to: Operand::Register(STACK_POINTER_BASE_REGISTER), 853 | })); 854 | // here, [rbp-1] is old base pointer 855 | // here, [rbp-2] is return address 856 | 857 | // body 858 | self.body.emit(instructions); 859 | 860 | // end of body 861 | // if return type is void, add return statement 862 | // else, add panic statement for missing return statement 863 | if instructions.get_true_typeinfo(&self.return_type) == TypeInfo::Void { 864 | // force add return statement 865 | let return_statement = StmtReturn { expr: None }; 866 | return_statement.emit(instructions); 867 | } else { 868 | // panic 869 | instructions.push(Instruction::Panic(Panic { 870 | message: format!( 871 | "Function {} must return a {:?} value", 872 | &self.name, &self.return_type 873 | ), 874 | })); 875 | } 876 | 877 | instructions.pop_scope(); 878 | instructions.function_scope = None; 879 | } 880 | } 881 | 882 | #[derive(Debug, Clone)] 883 | pub struct TranslationUnit { 884 | pub statements: Vec, 885 | } 886 | impl TranslationUnit { 887 | pub fn emit(&self, instructions: &mut InstructionGenerator) { 888 | for statement in &self.statements { 889 | statement.emit(instructions); 890 | } 891 | 892 | // find main function 893 | let _main = instructions 894 | .functions 895 | .get("main") 896 | .expect("main function not found"); 897 | 898 | let startaddress = instructions.instructions.len(); 899 | instructions.start_address = startaddress; 900 | instructions.push(Instruction::Call(Call { 901 | label: "main".to_string(), 902 | })); 903 | } 904 | } 905 | -------------------------------------------------------------------------------- /src/ast/typename.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | use generation::InstructionGenerator; 4 | 5 | use crate::virtualmachine::instruction::operand::Operand; 6 | use crate::virtualmachine::{ 7 | instruction::*, program::STACK_POINTER_REGISTER, variable::VariableData, 8 | }; 9 | 10 | use super::expression::Expression; 11 | 12 | #[derive(Debug, Clone, PartialEq)] 13 | pub enum TypeInfo { 14 | Void, 15 | Int8, 16 | Int16, 17 | Int32, 18 | Int64, 19 | UInt8, 20 | UInt16, 21 | UInt32, 22 | UInt64, 23 | Float32, 24 | Float64, 25 | Struct(StructInfo), 26 | Union(UnionInfo), 27 | Enum(EnumInfo), 28 | Pointer(Box), 29 | Array(Box, Option), 30 | Function(Box, Vec), 31 | Const(Box), 32 | 33 | // for typedef 34 | // temporary store the name of the type; will be replaced by the actual type in emitting 35 | Identifier(String), 36 | } 37 | impl Default for TypeInfo { 38 | fn default() -> Self { 39 | TypeInfo::Int32 40 | } 41 | } 42 | impl TypeInfo { 43 | pub fn sizeof(&self) -> usize { 44 | match self { 45 | TypeInfo::Void => panic!("sizeof(void) is invalid"), 46 | TypeInfo::Int8 => 1, 47 | TypeInfo::Int16 => 2, 48 | TypeInfo::Int32 => 4, 49 | TypeInfo::Int64 => 8, 50 | TypeInfo::UInt8 => 1, 51 | TypeInfo::UInt16 => 2, 52 | TypeInfo::UInt32 => 4, 53 | TypeInfo::UInt64 => 8, 54 | TypeInfo::Float32 => 4, 55 | TypeInfo::Float64 => 8, 56 | TypeInfo::Struct(info) => info.sizeof(), 57 | TypeInfo::Union(info) => info.sizeof(), 58 | TypeInfo::Enum(_) => 8, 59 | TypeInfo::Pointer(_) => 8, 60 | TypeInfo::Array(info, size) => { 61 | info.sizeof() * size.expect("sizeof: Array size is not defined") 62 | } 63 | TypeInfo::Function(_, _) => panic!("sizeof(function) is invalid"), 64 | TypeInfo::Identifier(_) => panic!("sizeof(identifier) is invalid"), 65 | TypeInfo::Const(t) => t.sizeof(), 66 | } 67 | } 68 | pub fn number_of_primitives(&self) -> usize { 69 | match self { 70 | TypeInfo::Void => 0, 71 | TypeInfo::Int8 | TypeInfo::Int16 | TypeInfo::Int32 | TypeInfo::Int64 => 1, 72 | TypeInfo::UInt8 | TypeInfo::UInt16 | TypeInfo::UInt32 | TypeInfo::UInt64 => 1, 73 | TypeInfo::Float32 | TypeInfo::Float64 => 1, 74 | TypeInfo::Struct(structinfo) => structinfo.number_of_primitives(), 75 | TypeInfo::Pointer(_) => 1, 76 | TypeInfo::Array(info, Some(size)) => info.number_of_primitives() * size, 77 | TypeInfo::Const(t) => t.number_of_primitives(), 78 | _ => panic!("number_of_primitives: unsupported type: {:?}", self), 79 | } 80 | } 81 | // push default value to the stack 82 | pub fn emit_default(&self, instructions: &mut InstructionGenerator) { 83 | match self { 84 | TypeInfo::UInt8 => instructions.push(Instruction::PushStack(PushStack { 85 | operand: Operand::Value(VariableData::UInt8(0)), 86 | })), 87 | TypeInfo::Int8 => instructions.push(Instruction::PushStack(PushStack { 88 | operand: Operand::Value(VariableData::Int8(0)), 89 | })), 90 | 91 | TypeInfo::UInt16 => instructions.push(Instruction::PushStack(PushStack { 92 | operand: Operand::Value(VariableData::UInt16(0)), 93 | })), 94 | TypeInfo::Int16 => instructions.push(Instruction::PushStack(PushStack { 95 | operand: Operand::Value(VariableData::Int16(0)), 96 | })), 97 | 98 | TypeInfo::UInt32 => instructions.push(Instruction::PushStack(PushStack { 99 | operand: Operand::Value(VariableData::UInt32(0)), 100 | })), 101 | TypeInfo::Int32 => instructions.push(Instruction::PushStack(PushStack { 102 | operand: Operand::Value(VariableData::Int32(0)), 103 | })), 104 | 105 | TypeInfo::UInt64 => instructions.push(Instruction::PushStack(PushStack { 106 | operand: Operand::Value(VariableData::UInt64(0)), 107 | })), 108 | TypeInfo::Int64 => instructions.push(Instruction::PushStack(PushStack { 109 | operand: Operand::Value(VariableData::Int64(0)), 110 | })), 111 | 112 | TypeInfo::Float32 => instructions.push(Instruction::PushStack(PushStack { 113 | operand: Operand::Value(VariableData::Float32(0.0)), 114 | })), 115 | 116 | TypeInfo::Float64 => instructions.push(Instruction::PushStack(PushStack { 117 | operand: Operand::Value(VariableData::Float64(0.0)), 118 | })), 119 | 120 | TypeInfo::Pointer(_) => instructions.push(Instruction::PushStack(PushStack { 121 | operand: Operand::Value(VariableData::UInt64(0)), 122 | })), 123 | 124 | TypeInfo::Array(t, Some(n)) => { 125 | for _ in 0..*n { 126 | t.emit_default(instructions); 127 | } 128 | } 129 | 130 | TypeInfo::Struct(info) => info.emit_default(instructions), 131 | 132 | TypeInfo::Const(t) => t.emit_default(instructions), 133 | 134 | _ => panic!("emit_default: unsupported type: {:?}", self), 135 | } 136 | } 137 | 138 | // initialize this type with the given initializer 139 | // and push to stack 140 | pub fn emit_init(&self, instructions: &mut InstructionGenerator, initializer: &Expression) { 141 | match self { 142 | TypeInfo::Array(t, Some(n)) => { 143 | let initializer = match initializer { 144 | Expression::InitializerList(initializer) => initializer, 145 | _ => { 146 | unreachable!( 147 | "TypeInfo::emit_init: initializer is not InitializerListExpression" 148 | ) 149 | } 150 | }; 151 | 152 | if initializer.initializers.len() > *n { 153 | panic!( 154 | "Array initialization overflow: expected {}, got {}", 155 | n, 156 | initializer.initializers.len() 157 | ); 158 | } 159 | 160 | for i in 0..initializer.initializers.len() { 161 | t.emit_init(instructions, &initializer.initializers[i]); 162 | } 163 | 164 | let remaining = *n - initializer.initializers.len(); 165 | for _ in 0..remaining { 166 | t.emit_default(instructions); 167 | } 168 | } 169 | 170 | TypeInfo::Struct(info) => info.emit_init(instructions, &initializer), 171 | 172 | TypeInfo::Const(t) => t.emit_init(instructions, &initializer), 173 | 174 | TypeInfo::UInt8 175 | | TypeInfo::Int8 176 | | TypeInfo::UInt16 177 | | TypeInfo::Int16 178 | | TypeInfo::UInt32 179 | | TypeInfo::Int32 180 | | TypeInfo::UInt64 181 | | TypeInfo::Int64 182 | | TypeInfo::Float32 183 | | TypeInfo::Float64 184 | | TypeInfo::Pointer(_) => { 185 | // check if it is initializer list 186 | match initializer { 187 | Expression::InitializerList(initializer) => { 188 | if initializer.initializers.len() != 1 { 189 | panic!( 190 | "TypeInfo::emit_init: initializer length mismatch: expected 1, got {}", 191 | initializer.initializers.len() 192 | ); 193 | } 194 | self.emit_init(instructions, &initializer.initializers[0]); 195 | } 196 | _ => { 197 | // register0 = initial value 198 | initializer.emit(instructions); 199 | 200 | // register1 = (type-casting) register0 201 | if initializer.is_return_reference(instructions) { 202 | instructions.push(Instruction::Assign(Assign { 203 | lhs_type: self.clone(), 204 | lhs: Operand::Register(1), 205 | rhs: Operand::Derefed(0, 0), 206 | })); 207 | } else { 208 | instructions.push(Instruction::Assign(Assign { 209 | lhs_type: self.clone(), 210 | lhs: Operand::Register(1), 211 | rhs: Operand::Register(0), 212 | })); 213 | } 214 | // push register1 to stack 215 | instructions.push(Instruction::PushStack(PushStack { 216 | operand: Operand::Register(1), 217 | })); 218 | } 219 | } 220 | } 221 | _ => panic!("emit_init: unsupported type: {:?}", self), 222 | } 223 | } 224 | 225 | // remove outermost const recursively 226 | pub fn remove_const(&self) -> TypeInfo { 227 | match self { 228 | TypeInfo::Const(t) => t.remove_const(), 229 | _ => self.clone(), 230 | } 231 | } 232 | 233 | pub fn add_const(&self) -> TypeInfo { 234 | match self { 235 | TypeInfo::Const(_) => self.clone(), 236 | _ => TypeInfo::Const(Box::new(self.clone())), 237 | } 238 | } 239 | pub fn is_const(&self) -> bool { 240 | match self { 241 | TypeInfo::Const(_) => true, 242 | _ => false, 243 | } 244 | } 245 | } 246 | 247 | #[derive(Debug, Clone, PartialEq)] 248 | pub struct StructInfo { 249 | pub name: Option, 250 | pub fields: Option>, 251 | } 252 | impl StructInfo { 253 | pub fn sizeof(&self) -> usize { 254 | let mut size: usize = 0; 255 | for (t, _, _) in self.fields.as_ref().unwrap() { 256 | size += t.sizeof(); 257 | } 258 | size 259 | } 260 | pub fn number_of_primitives(&self) -> usize { 261 | let mut count: usize = 0; 262 | for (t, _, _) in self.fields.as_ref().unwrap() { 263 | count += t.number_of_primitives(); 264 | } 265 | count 266 | } 267 | pub fn emit_default(&self, instructions: &mut InstructionGenerator) { 268 | for (t, _, _) in self.fields.as_ref().unwrap() { 269 | t.emit_default(instructions); 270 | } 271 | } 272 | pub fn emit_init(&self, instructions: &mut InstructionGenerator, initializer: &Expression) { 273 | match initializer { 274 | Expression::InitializerList(initializer) => { 275 | // struct init with initializer 276 | 277 | if initializer.initializers.len() != self.fields.as_ref().unwrap().len() { 278 | panic!( 279 | "StructInfo::emit_init: initializer length mismatch: expected {}, got {}", 280 | self.fields.as_ref().unwrap().len(), 281 | initializer.initializers.len() 282 | ); 283 | } 284 | 285 | for i in 0..initializer.initializers.len() { 286 | let (t, _, _) = &self.fields.as_ref().unwrap()[i]; 287 | instructions 288 | .get_true_typeinfo(t) 289 | .emit_init(instructions, &initializer.initializers[i]); 290 | } 291 | } 292 | _ => { 293 | // struct init with other struct 294 | if let TypeInfo::Struct(rhs_type) = initializer.get_typeinfo(instructions) { 295 | if self != &rhs_type { 296 | panic!("struct init: type mismatch1"); 297 | } 298 | 299 | let primitive_count = rhs_type.number_of_primitives(); 300 | 301 | initializer.emit(instructions); 302 | instructions.push(Instruction::MoveRegister(MoveRegister { 303 | operand_from: Operand::Register(0), 304 | operand_to: Operand::Register(1), 305 | })); 306 | 307 | // start address of new struct 308 | instructions.push(Instruction::MoveRegister(MoveRegister { 309 | operand_from: Operand::Register(STACK_POINTER_REGISTER), 310 | operand_to: Operand::Register(0), 311 | })); 312 | // alloc stack 313 | instructions.push(Instruction::AddAssign(AddAssign { 314 | lhs: Operand::Register(STACK_POINTER_REGISTER), 315 | rhs: Operand::Value(VariableData::UInt64(primitive_count as u64)), 316 | })); 317 | 318 | instructions.push(Instruction::AssignStruct(AssignStruct { 319 | lhs: Operand::Register(0), 320 | rhs: Operand::Register(1), 321 | count: primitive_count, 322 | })); 323 | } else { 324 | panic!("struct init: type mismatch2"); 325 | } 326 | } 327 | } 328 | } 329 | } 330 | #[derive(Debug, Clone, PartialEq)] 331 | pub struct UnionInfo { 332 | pub name: Option, 333 | pub fields: Option>, 334 | } 335 | impl UnionInfo { 336 | pub fn sizeof(&self) -> usize { 337 | let mut size: usize = 0; 338 | for (_, field) in self.fields.as_ref().unwrap() { 339 | size = size.max(field.sizeof()); 340 | } 341 | size 342 | } 343 | } 344 | 345 | #[derive(Debug, Clone, PartialEq)] 346 | pub struct EnumInfo { 347 | pub name: Option, 348 | pub fields: Option>, 349 | } 350 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use std::io::{stdin, stdout, Read, Write}; 2 | 3 | use virtualmachine::instruction::generation::InstructionGenerator; 4 | use virtualmachine::program::VirtualMachine; 5 | 6 | mod ast; 7 | mod preprocess; 8 | mod token; 9 | mod virtualmachine; 10 | 11 | fn main() { 12 | println!("Enter your code (and ^D for EOF):"); 13 | stdout().flush().expect("Failed to flush stdout"); 14 | 15 | // Read from stdin 16 | let mut source: Vec = Vec::new(); 17 | stdin() 18 | .read_to_end(&mut source) 19 | .expect("Failed to read from stdin"); 20 | 21 | let source = String::from_utf8(source).expect("Invalid UTF-8"); 22 | let preprocessor = preprocess::parser::PreprocessorParser::new(); 23 | 24 | // tokenize 25 | println!("{:=^80}", ""); 26 | println!("{:=^80}", "Phase1: Tokenizing"); 27 | println!("{:=^80}", ""); 28 | println!("LINE | {:-^73}", "Result"); 29 | let tokens = preprocessor.tokenize(&source); 30 | let mut linestart = true; 31 | let mut lineid = 0; 32 | for token in tokens.iter() { 33 | if linestart { 34 | print!("{:4}: ", lineid); 35 | } 36 | if token == &token::Token::NewLine { 37 | println!(); 38 | linestart = true; 39 | lineid += 1; 40 | } else { 41 | print!("{:?} ", token); 42 | linestart = false; 43 | } 44 | } 45 | 46 | // line analysis 47 | println!("{:=^80}", ""); 48 | println!("{:=^80}", "Phase2: Line Analysis"); 49 | println!("{:=^80}", ""); 50 | println!("LINE | {:-^73}", "Result"); 51 | let lines = preprocessor.parse_lines(&tokens); 52 | for (lineid, line) in lines.iter().enumerate() { 53 | println!("{:4}: {:?}", lineid, line); 54 | } 55 | 56 | // preprocess 57 | println!("{:=^80}", ""); 58 | println!("{:=^80}", "Phase3: Preprocessing"); 59 | println!("{:=^80}", ""); 60 | println!("LINE | {:-^73}", "Result"); 61 | let line_tokenized = preprocessor.preprocess(&lines); 62 | 63 | for (lineid, line) in line_tokenized.iter().enumerate() { 64 | println!("{:4}: {:?}", lineid, line); 65 | } 66 | 67 | // flatten the line_tokenized 68 | let tokens: Vec = line_tokenized.into_iter().flatten().collect(); 69 | 70 | println!("{:=^80}", ""); 71 | println!("{:=^80}", "Phase4: Building AbstractSyntaxTree"); 72 | println!("{:=^80}", ""); 73 | 74 | // parse the tokens into AST 75 | println!("ASTs: "); 76 | let parser = ast::parser::ASTParser::new(); 77 | let translation_unit = parser.parse(tokens); 78 | println!("{:#?}", translation_unit); 79 | 80 | // generate instructions 81 | println!("{:=^80}", ""); 82 | println!("{:=^80}", "Phase5: Generating Instructions"); 83 | println!("{:=^80}", ""); 84 | println!("ADDR | {:-^73}", "Result"); 85 | 86 | let mut instructions: InstructionGenerator = InstructionGenerator::new(); 87 | translation_unit.emit(&mut instructions); 88 | 89 | println!("Instructions: "); 90 | for (id, instruction) in instructions.instructions.iter().enumerate() { 91 | if id == instructions.start_address { 92 | println!("{: ^2}{:-^78}", "", "Start Address"); 93 | } 94 | println!("{:4}: {:?}", id, instruction); 95 | } 96 | 97 | // execute instructions 98 | println!("{:=^80}", ""); 99 | println!("{:=^80}", "Phase6: Executing Instructions"); 100 | println!("{:=^80}", ""); 101 | let mut vm: VirtualMachine = VirtualMachine::new(); 102 | vm.execute(&mut instructions); 103 | 104 | stdout().flush().expect("Failed to flush stdout"); 105 | } 106 | -------------------------------------------------------------------------------- /src/preprocess/context.rs: -------------------------------------------------------------------------------- 1 | use crate::token::Token; 2 | use std::collections::HashMap; 3 | use std::vec::Vec; 4 | 5 | pub enum MacroData { 6 | DirectReplace(Vec), 7 | Function(usize, Vec), 8 | } 9 | 10 | pub struct IfStackData { 11 | pub processed: bool, // if some branch of the #if-#elif chain has been processed 12 | pub current: bool, // if current branch is active 13 | } 14 | 15 | pub struct PreprocessorContext { 16 | pub define_map: HashMap, 17 | 18 | pub if_stack: Vec, 19 | } 20 | impl PreprocessorContext { 21 | pub fn new() -> Self { 22 | Self { 23 | define_map: HashMap::new(), 24 | if_stack: Vec::new(), 25 | } 26 | } 27 | 28 | // check if the current context should emit tokens; 29 | // returns false if it is false branch of an #if directive 30 | pub fn should_emit(&self) -> bool { 31 | if self.if_stack.is_empty() { 32 | true 33 | } else { 34 | self.if_stack.last().unwrap().current 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/preprocess/expression.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Debug; 2 | 3 | use super::context::PreprocessorContext; 4 | 5 | #[derive(Debug, Clone)] 6 | pub enum UnaryOperator { 7 | Plus, 8 | Minus, 9 | LogicalNot, 10 | BitwiseNot, 11 | } 12 | 13 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 14 | pub enum BinaryOperator { 15 | Add, 16 | Sub, 17 | Mul, 18 | Div, 19 | Mod, 20 | BitwiseAnd, 21 | BitwiseOr, 22 | BitwiseXor, 23 | LogicalAnd, 24 | LogicalOr, 25 | ShiftLeft, 26 | ShiftRight, 27 | LessThan, 28 | GreaterThan, 29 | LessThanOrEqual, 30 | GreaterThanOrEqual, 31 | Equal, 32 | NotEqual, 33 | } 34 | 35 | pub trait PreprocessorExpression: Debug { 36 | fn eval(&self, ctx: &mut PreprocessorContext) -> i64; 37 | } 38 | 39 | #[derive(Debug)] 40 | pub struct Constant { 41 | pub value: i64, 42 | } 43 | impl PreprocessorExpression for Constant { 44 | fn eval(&self, _ctx: &mut PreprocessorContext) -> i64 { 45 | self.value 46 | } 47 | } 48 | 49 | #[derive(Debug)] 50 | pub struct Defined { 51 | pub name: String, 52 | } 53 | impl PreprocessorExpression for Defined { 54 | fn eval(&self, ctx: &mut PreprocessorContext) -> i64 { 55 | if ctx.define_map.contains_key(&self.name) { 56 | 1 57 | } else { 58 | 0 59 | } 60 | } 61 | } 62 | 63 | #[derive(Debug)] 64 | pub struct UnaryExpression { 65 | pub op: UnaryOperator, 66 | pub src: Box, 67 | } 68 | impl PreprocessorExpression for UnaryExpression { 69 | fn eval(&self, ctx: &mut PreprocessorContext) -> i64 { 70 | match self.op { 71 | UnaryOperator::Plus => self.src.eval(ctx), 72 | UnaryOperator::Minus => -self.src.eval(ctx), 73 | UnaryOperator::LogicalNot => { 74 | if self.src.eval(ctx) == 0 { 75 | 1 76 | } else { 77 | 0 78 | } 79 | } 80 | UnaryOperator::BitwiseNot => !self.src.eval(ctx), 81 | } 82 | } 83 | } 84 | 85 | #[derive(Debug)] 86 | pub struct BinaryExpression { 87 | pub op: BinaryOperator, 88 | pub lhs: Box, 89 | pub rhs: Box, 90 | } 91 | impl PreprocessorExpression for BinaryExpression { 92 | fn eval(&self, ctx: &mut PreprocessorContext) -> i64 { 93 | let lhs = self.lhs.eval(ctx); 94 | let rhs = self.rhs.eval(ctx); 95 | match self.op { 96 | BinaryOperator::Add => lhs + rhs, 97 | BinaryOperator::Sub => lhs - rhs, 98 | BinaryOperator::Mul => lhs * rhs, 99 | BinaryOperator::Div => lhs / rhs, 100 | BinaryOperator::Mod => lhs % rhs, 101 | BinaryOperator::BitwiseAnd => lhs & rhs, 102 | BinaryOperator::BitwiseOr => lhs | rhs, 103 | BinaryOperator::BitwiseXor => lhs ^ rhs, 104 | BinaryOperator::LogicalAnd => { 105 | if lhs != 0 && rhs != 0 { 106 | 1 107 | } else { 108 | 0 109 | } 110 | } 111 | BinaryOperator::LogicalOr => { 112 | if lhs != 0 || rhs != 0 { 113 | 1 114 | } else { 115 | 0 116 | } 117 | } 118 | BinaryOperator::ShiftLeft => lhs << rhs, 119 | BinaryOperator::ShiftRight => lhs >> rhs, 120 | BinaryOperator::LessThan => { 121 | if lhs < rhs { 122 | 1 123 | } else { 124 | 0 125 | } 126 | } 127 | BinaryOperator::GreaterThan => { 128 | if lhs > rhs { 129 | 1 130 | } else { 131 | 0 132 | } 133 | } 134 | BinaryOperator::LessThanOrEqual => { 135 | if lhs <= rhs { 136 | 1 137 | } else { 138 | 0 139 | } 140 | } 141 | BinaryOperator::GreaterThanOrEqual => { 142 | if lhs >= rhs { 143 | 1 144 | } else { 145 | 0 146 | } 147 | } 148 | BinaryOperator::Equal => { 149 | if lhs == rhs { 150 | 1 151 | } else { 152 | 0 153 | } 154 | } 155 | BinaryOperator::NotEqual => { 156 | if lhs != rhs { 157 | 1 158 | } else { 159 | 0 160 | } 161 | } 162 | } 163 | } 164 | } 165 | 166 | #[derive(Debug)] 167 | pub struct ConditionalExpression { 168 | pub cond: Box, 169 | pub then_expr: Box, 170 | pub else_expr: Box, 171 | } 172 | impl PreprocessorExpression for ConditionalExpression { 173 | fn eval(&self, ctx: &mut PreprocessorContext) -> i64 { 174 | let cond = self.cond.eval(ctx); 175 | if cond != 0 { 176 | self.then_expr.eval(ctx) 177 | } else { 178 | self.else_expr.eval(ctx) 179 | } 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /src/preprocess/mod.rs: -------------------------------------------------------------------------------- 1 | pub(crate) mod context; 2 | pub(crate) mod expression; 3 | pub(crate) mod parser; 4 | pub(crate) mod preprocessor; 5 | -------------------------------------------------------------------------------- /src/preprocess/parser.rs: -------------------------------------------------------------------------------- 1 | use std::boxed::Box; 2 | use std::cell::RefCell; 3 | use std::rc::Rc; 4 | 5 | use rp::IntoParser; 6 | use rusty_parser as rp; 7 | 8 | use super::context::*; 9 | use super::expression::*; 10 | use super::preprocessor::*; 11 | use crate::token::trie::ident_to_keyword_map; 12 | use crate::token::Token; 13 | 14 | pub struct PreprocessorParser { 15 | /// compile-time expression parser 16 | pub expression: Rc,), Token>>>, 17 | 18 | /// comma-separated list of macro arguments 19 | pub macro_argument_item_list: Rc>,), Token>>>, 20 | 21 | /// parse one line of token stream and make AST for preprocessing 22 | pub line: Rc,), Token>>>, 23 | } 24 | 25 | impl PreprocessorParser { 26 | pub fn new() -> Self { 27 | let s = Self { 28 | expression: Default::default(), 29 | macro_argument_item_list: Default::default(), 30 | line: Default::default(), 31 | }; 32 | 33 | s.expression_parser(); 34 | s.arg_list_parser(); 35 | s.line_parser(); 36 | 37 | s 38 | } 39 | 40 | fn expression_parser(&self) { 41 | let primary_expression: Rc< 42 | RefCell,), Token>>, 43 | > = Default::default(); 44 | let unary_expression: Rc< 45 | RefCell,), Token>>, 46 | > = Default::default(); 47 | let multiplicative_expression: Rc< 48 | RefCell,), Token>>, 49 | > = Default::default(); 50 | let additive_expression: Rc< 51 | RefCell,), Token>>, 52 | > = Default::default(); 53 | let shift_expression: Rc< 54 | RefCell,), Token>>, 55 | > = Default::default(); 56 | let relational_expression: Rc< 57 | RefCell,), Token>>, 58 | > = Default::default(); 59 | let equality_expression: Rc< 60 | RefCell,), Token>>, 61 | > = Default::default(); 62 | let and_expression: Rc< 63 | RefCell,), Token>>, 64 | > = Default::default(); 65 | let exclusive_or_expression: Rc< 66 | RefCell,), Token>>, 67 | > = Default::default(); 68 | let inclusive_or_expression: Rc< 69 | RefCell,), Token>>, 70 | > = Default::default(); 71 | let logical_and_expression: Rc< 72 | RefCell,), Token>>, 73 | > = Default::default(); 74 | let logical_or_expression: Rc< 75 | RefCell,), Token>>, 76 | > = Default::default(); 77 | let conditional_expression: Rc< 78 | RefCell,), Token>>, 79 | > = Default::default(); 80 | 81 | // ======================= 82 | // Primary expression 83 | // ======================= 84 | { 85 | let integer_constant = rp::check(|t: Token| -> Option { 86 | match t { 87 | Token::ConstantUnsignedInteger(i) => Some(i as i64), 88 | Token::ConstantInteger(i) => Some(i as i64), 89 | Token::ConstantCharacter(ch) => Some(ch as i64), 90 | Token::ConstantLong(l) => Some(l as i64), 91 | Token::ConstantUnsignedLong(l) => Some(l as i64), 92 | _ => None, 93 | } 94 | }) 95 | .map(|i: i64| -> Box { Box::new(Constant { value: i }) }); 96 | 97 | let float_constant = rp::check(|t: Token| -> Option { 98 | match t { 99 | Token::ConstantFloat(f) => Some(f as f64), 100 | Token::ConstantDouble(f) => Some(f as f64), 101 | _ => None, 102 | } 103 | }) 104 | .map(|_: f64| -> Box { 105 | panic!("Float constant is not supported in preprocessing stage"); 106 | }); 107 | 108 | let defined = rp::seq!( 109 | rp::one(Token::Identifier("defined".to_string())).void(), 110 | rp::one(Token::LeftParen).void(), 111 | rp::check(|t: Token| -> Option { 112 | if let Token::Identifier(s) = t { 113 | Some(s) 114 | } else { 115 | None 116 | } 117 | }), 118 | rp::one(Token::RightParen).void() 119 | ) 120 | .map(|name: String| -> Box { Box::new(Defined { name }) }); 121 | 122 | primary_expression.borrow_mut().assign(rp::or!( 123 | integer_constant, 124 | float_constant, 125 | defined, 126 | rp::seq!( 127 | rp::one(Token::LeftParen).void(), 128 | self.expression.clone(), 129 | rp::one(Token::RightParen).void() 130 | ) 131 | )); 132 | } 133 | 134 | // ======================= 135 | // Unary expression 136 | // ======================= 137 | { 138 | /* 139 | unary_operator 140 | : '&' 141 | | '*' 142 | | '+' 143 | | '-' 144 | | '~' 145 | | '!' 146 | ; 147 | */ 148 | let unary_operator = rp::or!( 149 | rp::one(Token::Plus).output(UnaryOperator::Plus), 150 | rp::one(Token::Minus).output(UnaryOperator::Minus), 151 | rp::one(Token::Tilde).output(UnaryOperator::BitwiseNot), 152 | rp::one(Token::Exclamation).output(UnaryOperator::LogicalNot) 153 | ); 154 | 155 | /* 156 | unary_expression 157 | : postfix_expression 158 | | unary_operator cast_expression 159 | ; 160 | */ 161 | let unary_expression_ = rp::or!( 162 | rp::seq!(unary_operator, primary_expression.clone()).map( 163 | |op: UnaryOperator, 164 | expr: Box| 165 | -> Box { 166 | Box::new(UnaryExpression { op, src: expr }) 167 | } 168 | ), 169 | primary_expression.clone() 170 | ); 171 | 172 | unary_expression.borrow_mut().assign(unary_expression_); 173 | } 174 | 175 | { 176 | /* 177 | multiplicative_expression 178 | : unary_expression 179 | | multiplicative_expression '*' cast_expression 180 | | multiplicative_expression '/' cast_expression 181 | | multiplicative_expression '%' cast_expression 182 | ; 183 | */ 184 | let op = rp::or!( 185 | rp::one(Token::Star).output(BinaryOperator::Mul), 186 | rp::one(Token::Slash).output(BinaryOperator::Div), 187 | rp::one(Token::Percent).output(BinaryOperator::Mod) 188 | ); 189 | 190 | let multiplicative_ = unary_expression.clone().reduce_left( 191 | rp::seq!(op, unary_expression.clone()), 192 | |lhs: Box, 193 | op: BinaryOperator, 194 | rhs: Box| 195 | -> Box { 196 | Box::new(BinaryExpression { op, lhs, rhs }) 197 | }, 198 | ); 199 | multiplicative_expression 200 | .borrow_mut() 201 | .assign(multiplicative_); 202 | } 203 | { 204 | /* 205 | additive_expression 206 | : multiplicative_expression 207 | | additive_expression '+' multiplicative_expression 208 | | additive_expression '-' multiplicative_expression 209 | ; 210 | */ 211 | let op = rp::or!( 212 | rp::one(Token::Plus).output(BinaryOperator::Add), 213 | rp::one(Token::Minus).output(BinaryOperator::Sub) 214 | ); 215 | let additive = multiplicative_expression.clone().reduce_left( 216 | rp::seq!(op, multiplicative_expression.clone()), 217 | |lhs: Box, 218 | op: BinaryOperator, 219 | rhs: Box| 220 | -> Box { 221 | Box::new(BinaryExpression { op, lhs, rhs }) 222 | }, 223 | ); 224 | additive_expression.borrow_mut().assign(additive); 225 | } 226 | { 227 | /* 228 | shift_expression 229 | : additive_expression 230 | | shift_expression LEFT_OP additive_expression 231 | | shift_expression RIGHT_OP additive_expression 232 | ; 233 | */ 234 | let op = rp::or!( 235 | rp::one(Token::LeftOp).output(BinaryOperator::ShiftLeft), 236 | rp::one(Token::RightOp).output(BinaryOperator::ShiftRight) 237 | ); 238 | let shift = additive_expression.clone().reduce_left( 239 | rp::seq!(op, additive_expression.clone()), 240 | |lhs: Box, 241 | op: BinaryOperator, 242 | rhs: Box| 243 | -> Box { 244 | Box::new(BinaryExpression { op, lhs, rhs }) 245 | }, 246 | ); 247 | shift_expression.borrow_mut().assign(shift); 248 | } 249 | { 250 | /* 251 | relational_expression 252 | : shift_expression 253 | | relational_expression '<' shift_expression 254 | | relational_expression '>' shift_expression 255 | | relational_expression LE_OP shift_expression 256 | | relational_expression GE_OP shift_expression 257 | ; 258 | */ 259 | let op = rp::or!( 260 | rp::one(Token::LessThan).output(BinaryOperator::LessThan), 261 | rp::one(Token::GreaterThan).output(BinaryOperator::GreaterThan), 262 | rp::one(Token::LeOp).output(BinaryOperator::LessThanOrEqual), 263 | rp::one(Token::GeOp).output(BinaryOperator::GreaterThanOrEqual) 264 | ); 265 | let relational = shift_expression.clone().reduce_left( 266 | rp::seq!(op, shift_expression.clone()), 267 | |lhs: Box, 268 | op: BinaryOperator, 269 | rhs: Box| 270 | -> Box { 271 | Box::new(BinaryExpression { op, lhs, rhs }) 272 | }, 273 | ); 274 | relational_expression.borrow_mut().assign(relational); 275 | } 276 | { 277 | /* 278 | equality_expression 279 | : relational_expression 280 | | equality_expression EQ_OP relational_expression 281 | | equality_expression NE_OP relational_expression 282 | ; 283 | */ 284 | let op = rp::or!( 285 | rp::one(Token::EqOp).output(BinaryOperator::Equal), 286 | rp::one(Token::NeOp).output(BinaryOperator::NotEqual) 287 | ); 288 | let equality = relational_expression.clone().reduce_left( 289 | rp::seq!(op, relational_expression.clone()), 290 | |lhs: Box, 291 | op: BinaryOperator, 292 | rhs: Box| 293 | -> Box { 294 | Box::new(BinaryExpression { op, lhs, rhs }) 295 | }, 296 | ); 297 | equality_expression.borrow_mut().assign(equality); 298 | } 299 | { 300 | /* 301 | and_expression 302 | : equality_expression 303 | | and_expression '&' equality_expression 304 | ; 305 | */ 306 | let op = rp::one(Token::Ampersand).output(BinaryOperator::BitwiseAnd); 307 | let and = equality_expression.clone().reduce_left( 308 | rp::seq!(op, equality_expression.clone()), 309 | |lhs: Box, 310 | op: BinaryOperator, 311 | rhs: Box| 312 | -> Box { 313 | Box::new(BinaryExpression { op, lhs, rhs }) 314 | }, 315 | ); 316 | and_expression.borrow_mut().assign(and); 317 | } 318 | { 319 | /* 320 | exclusive_or_expression 321 | : and_expression 322 | | exclusive_or_expression '^' and_expression 323 | ; 324 | */ 325 | let op = rp::one(Token::Caret).output(BinaryOperator::BitwiseXor); 326 | let xor = and_expression.clone().reduce_left( 327 | rp::seq!(op, and_expression.clone()), 328 | |lhs: Box, 329 | op: BinaryOperator, 330 | rhs: Box| 331 | -> Box { 332 | Box::new(BinaryExpression { op, lhs, rhs }) 333 | }, 334 | ); 335 | exclusive_or_expression.borrow_mut().assign(xor); 336 | } 337 | { 338 | /* 339 | inclusive_or_expression 340 | : exclusive_or_expression 341 | | inclusive_or_expression '|' exclusive_or_expression 342 | ; 343 | */ 344 | let op = rp::one(Token::Pipe).output(BinaryOperator::BitwiseOr); 345 | let or = exclusive_or_expression.clone().reduce_left( 346 | rp::seq!(op, exclusive_or_expression.clone()), 347 | |lhs: Box, 348 | op: BinaryOperator, 349 | rhs: Box| 350 | -> Box { 351 | Box::new(BinaryExpression { op, lhs, rhs }) 352 | }, 353 | ); 354 | inclusive_or_expression.borrow_mut().assign(or); 355 | } 356 | { 357 | /* 358 | logical_and_expression 359 | : inclusive_or_expression 360 | | logical_and_expression AND_OP inclusive_or_expression 361 | ; 362 | */ 363 | let op = rp::one(Token::AndOp).output(BinaryOperator::LogicalAnd); 364 | let logical_and = inclusive_or_expression.clone().reduce_left( 365 | rp::seq!(op, inclusive_or_expression.clone()), 366 | |lhs: Box, 367 | op: BinaryOperator, 368 | rhs: Box| 369 | -> Box { 370 | Box::new(BinaryExpression { op, lhs, rhs }) 371 | }, 372 | ); 373 | logical_and_expression.borrow_mut().assign(logical_and); 374 | } 375 | { 376 | /* 377 | logical_or_expression 378 | : logical_and_expression 379 | | logical_or_expression OR_OP logical_and_expression 380 | ; 381 | */ 382 | 383 | let op = rp::one(Token::OrOp).output(BinaryOperator::LogicalOr); 384 | let logical_or = logical_and_expression.clone().reduce_left( 385 | rp::seq!(op, logical_and_expression.clone()), 386 | |lhs: Box, 387 | op: BinaryOperator, 388 | rhs: Box| 389 | -> Box { 390 | Box::new(BinaryExpression { op, lhs, rhs }) 391 | }, 392 | ); 393 | logical_or_expression.borrow_mut().assign(logical_or); 394 | } 395 | { 396 | /* 397 | conditional_expression 398 | : logical_or_expression 399 | | logical_or_expression '?' expression ':' conditional_expression 400 | ; 401 | */ 402 | let conditional = rp::seq!( 403 | logical_or_expression.clone(), 404 | rp::seq!( 405 | rp::one(Token::Question).void(), 406 | self.expression 407 | .clone() 408 | .or_else(|| -> Box { 409 | panic!("Invalid expression after '?' in conditional expression"); 410 | }), 411 | rp::one(Token::Colon).void().or_else(|| -> () { 412 | panic!("Colon ':' expected after '?' in conditional expression"); 413 | }), 414 | conditional_expression.clone().or_else( 415 | || -> Box { 416 | panic!("Invalid expression after ':' in conditional expression"); 417 | } 418 | ) 419 | ) 420 | .optional() 421 | ) 422 | .map( 423 | |cond: Box, 424 | truefalse: Option<( 425 | Box, 426 | Box, 427 | )>| 428 | -> Box { 429 | if let Some((true_expr, false_expr)) = truefalse { 430 | Box::new(ConditionalExpression { 431 | cond, 432 | then_expr: true_expr, 433 | else_expr: false_expr, 434 | }) 435 | } else { 436 | cond 437 | } 438 | }, 439 | ); 440 | conditional_expression 441 | .borrow_mut() 442 | .assign(conditional.clone()); 443 | self.expression.borrow_mut().assign(conditional); 444 | } 445 | } 446 | 447 | fn arg_list_parser(&self) { 448 | let macro_argument_item: Rc,), Token>>> = 449 | Default::default(); 450 | let macro_argument_item_list: Rc>,), Token>>> = 451 | Default::default(); 452 | 453 | let single_item = rp::any() 454 | .not(rp::or!(rp::one(Token::Comma), rp::one(Token::RightParen))) 455 | .repeat(0..); 456 | let parenthesized_list = rp::seq!( 457 | rp::one(Token::LeftParen).void(), 458 | macro_argument_item_list.clone(), 459 | rp::one(Token::RightParen).void() 460 | ) 461 | .map(|mut args: Vec>| { 462 | let mut v = Vec::new(); 463 | v.push(Token::LeftParen); 464 | for (idx, arg) in args.iter_mut().enumerate() { 465 | if idx > 0 { 466 | v.push(Token::Comma); 467 | } 468 | v.append(arg); 469 | } 470 | v.push(Token::RightParen); 471 | v 472 | }); 473 | // macro_argument_item.borrow_mut().assign(single_item); 474 | macro_argument_item 475 | .borrow_mut() 476 | .assign(rp::or!(parenthesized_list, single_item)); 477 | 478 | let single_item_list = macro_argument_item 479 | .clone() 480 | .map(|item: Vec| -> Vec> { vec![item] }) 481 | .reduce_left( 482 | rp::seq!(rp::one(Token::Comma).void(), macro_argument_item.clone()), 483 | |mut v: Vec>, item: Vec| { 484 | v.push(item); 485 | v 486 | }, 487 | ); 488 | self.macro_argument_item_list 489 | .borrow_mut() 490 | .assign(single_item_list); 491 | } 492 | 493 | fn line_parser(&self) { 494 | // String 495 | let identifier_parser = rp::check(|t| { 496 | if let Token::Identifier(name) = t { 497 | Some(name) 498 | } else { 499 | None 500 | } 501 | }); 502 | // identifier, identifier, ... 503 | // Vec 504 | let identifiers_parser = identifier_parser.map(|s: String| vec![s]).reduce_left( 505 | rp::seq!( 506 | rp::one(Token::Whitespace).optional().void(), 507 | rp::one(Token::Comma).void(), 508 | rp::one(Token::Whitespace).optional().void(), 509 | identifier_parser.clone() 510 | ), 511 | |mut v: Vec, s: String| { 512 | v.push(s); 513 | v 514 | }, 515 | ); 516 | 517 | // Vec excluing lineend 518 | let tokens_to_end = rp::seq!( 519 | rp::any().not(rp::one(Token::NewLine)).repeat(0..), 520 | rp::one(Token::NewLine).void() 521 | ) 522 | .map(|tokens: Vec| -> Vec { 523 | tokens 524 | .iter() 525 | .filter(|t| *t != &Token::Whitespace) 526 | .cloned() 527 | .collect() 528 | }); 529 | 530 | // ( macro_name: String, replace_tokens: Vec ) 531 | let define_identifier_parser = rp::seq!( 532 | rp::one(Token::PreprocessorDefine).void(), 533 | rp::one(Token::Whitespace).void().or_else(|| -> () { 534 | panic!("Whitespace expected after #define directive"); 535 | }), 536 | identifier_parser.clone().or_else(|| -> String { 537 | panic!("Identifier must come after #define"); 538 | }), 539 | rp::or!( 540 | rp::seq!(rp::one(Token::Whitespace).void(), tokens_to_end.clone()), 541 | rp::one(Token::NewLine).void().map(|| Vec::new()) 542 | ) 543 | .or_else(|| -> Vec { 544 | panic!("Invalid macro replacement"); 545 | }) 546 | ) 547 | .map( 548 | |name: String, replacement: Vec| -> Box { 549 | Box::new(Define { name, replacement }) 550 | }, 551 | ); 552 | 553 | // ( macro_name: String, macro_params: Vec, macro_value: Vec ) 554 | let define_function_parser = rp::seq!( 555 | rp::one(Token::PreprocessorDefine).void(), 556 | rp::one(Token::Whitespace).void().or_else(|| -> () { 557 | panic!("Whitespace expected after #define directive"); 558 | }), 559 | identifier_parser.clone().or_else(|| -> String { 560 | panic!("Identifier must come after #define"); 561 | }), 562 | rp::one(Token::LeftParen).void(), 563 | rp::one(Token::Whitespace).optional().void(), 564 | identifiers_parser.or_else(|| -> Vec { 565 | panic!("Invalid macro parameters; must be comma-separated identifiers"); 566 | }), 567 | rp::one(Token::Whitespace).optional().void(), 568 | rp::one(Token::RightParen).void().or_else(|| -> () { 569 | panic!("RightParen ')' expected after macro parameters"); 570 | },), 571 | // replacement 572 | rp::or!( 573 | rp::seq!(rp::one(Token::Whitespace).void(), tokens_to_end.clone()), 574 | rp::one(Token::NewLine).void().map(|| Vec::new()) 575 | ) 576 | .or_else(|| -> Vec { 577 | panic!("Invalid macro replacement"); 578 | }) 579 | ) 580 | .map( 581 | |name: String, 582 | params: Vec, 583 | mut replacement: Vec| 584 | -> Box { 585 | for (idx, param_name) in params.iter().enumerate() { 586 | for token in replacement.iter_mut() { 587 | if let Token::Identifier(ref s) = token { 588 | if s == param_name { 589 | *token = Token::PreprocessorPlaceholder(idx); 590 | } 591 | } 592 | } 593 | } 594 | Box::new(DefineFunction { 595 | name, 596 | param_count: params.len(), 597 | replacement: replacement, 598 | }) 599 | }, 600 | ); 601 | 602 | let undef_parser = rp::seq!( 603 | rp::one(Token::PreprocessorUndef).void(), 604 | rp::one(Token::Whitespace).void().or_else(|| -> () { 605 | panic!("Whitespace expected after #undef directive"); 606 | }), 607 | identifier_parser.clone().or_else(|| -> String { 608 | panic!("Identifier must come after #undef"); 609 | }), 610 | rp::one(Token::Whitespace).optional().void(), 611 | rp::one(Token::NewLine).void().or_else(|| -> () { 612 | panic!("unexpected token after #undef IDENTIFIER"); 613 | }) 614 | ) 615 | .map(|name: String| -> Box { Box::new(Undef { name }) }); 616 | 617 | let ifdef_parser = rp::seq!( 618 | rp::one(Token::PreprocessorIfDef).void(), 619 | rp::one(Token::Whitespace).void().or_else(|| -> () { 620 | panic!("Whitespace expected after #ifdef directive"); 621 | }), 622 | identifier_parser.clone().or_else(|| -> String { 623 | panic!("Identifier must come after #ifdef"); 624 | }), 625 | rp::one(Token::Whitespace).optional().void(), 626 | rp::one(Token::NewLine).void().or_else(|| -> () { 627 | panic!("unexpected token after #ifdef IDENTIFIER"); 628 | }) 629 | ) 630 | .map(|name: String| -> Box { Box::new(IfDef { name }) }); 631 | 632 | let ifndef_parser = rp::seq!( 633 | rp::one(Token::PreprocessorIfNDef).void(), 634 | rp::one(Token::Whitespace).void().or_else(|| -> () { 635 | panic!("Whitespace expected after #ifndef directive"); 636 | }), 637 | identifier_parser.clone().or_else(|| -> String { 638 | panic!("Identifier must come after #ifndef"); 639 | }), 640 | rp::one(Token::Whitespace).optional().void(), 641 | rp::one(Token::NewLine).void().or_else(|| -> () { 642 | panic!("unexpected token after #ifndef IDENTIFIER"); 643 | }) 644 | ) 645 | .map(|name: String| -> Box { Box::new(IfNDef { name }) }); 646 | 647 | let else_parser = rp::seq!( 648 | rp::one(Token::PreprocessorElse).void(), 649 | rp::one(Token::Whitespace).optional().void(), 650 | rp::one(Token::NewLine).void().or_else(|| -> () { 651 | panic!("unexpected token after #else"); 652 | }) 653 | ) 654 | .map(|| -> Box { Box::new(Else {}) }); 655 | 656 | let endif_parser = rp::seq!( 657 | rp::one(Token::PreprocessorEndIf).void(), 658 | rp::one(Token::Whitespace).optional().void(), 659 | rp::one(Token::NewLine).void().or_else(|| -> () { 660 | panic!("unexpected token after #endif"); 661 | }) 662 | ) 663 | .map(|| -> Box { Box::new(EndIf {}) }); 664 | 665 | let if_parser = rp::seq!( 666 | rp::one(Token::PreprocessorIf).void(), 667 | rp::one(Token::Whitespace).void().or_else(|| -> () { 668 | panic!("Whitespace expected after #if directive"); 669 | }), 670 | tokens_to_end.clone() 671 | ) 672 | .map( 673 | |expr_tokens: Vec| -> Box { 674 | Box::new(If { 675 | expression_tokens: expr_tokens, 676 | }) 677 | }, 678 | ); 679 | 680 | let elif_parser = rp::seq!( 681 | rp::one(Token::PreprocessorElIf).void(), 682 | rp::one(Token::Whitespace).void().or_else(|| -> () { 683 | panic!("Whitespace expected after #elif directive"); 684 | }), 685 | tokens_to_end.clone() 686 | ) 687 | .map( 688 | |expr_tokens: Vec| -> Box { 689 | Box::new(ElIf { 690 | expression_tokens: expr_tokens, 691 | }) 692 | }, 693 | ); 694 | 695 | // token stream as-is without any processing, excluding lineend 696 | let raw_parser = 697 | tokens_to_end 698 | .clone() 699 | .map(|tokens: Vec| -> Box { 700 | Box::new(RawTokens { tokens }) 701 | }); 702 | 703 | self.line.borrow_mut().assign(rp::seq!( 704 | rp::one(Token::Whitespace).optional().void(), 705 | rp::or!( 706 | define_function_parser, 707 | define_identifier_parser, 708 | undef_parser, 709 | ifdef_parser, 710 | ifndef_parser, 711 | if_parser, 712 | elif_parser, 713 | else_parser, 714 | endif_parser, 715 | raw_parser 716 | ) 717 | )); 718 | } 719 | 720 | pub fn tokenize(&self, source: &str) -> Vec { 721 | let tokens = crate::token::tokenize::tokenize(source); 722 | tokens 723 | } 724 | 725 | pub fn parse_lines(&self, tokens: &[Token]) -> Vec> { 726 | let lines_parser = rp::seq!(self.line.clone().repeat(0..), rp::end()); 727 | 728 | // build ast 729 | let lines_result = rp::parse(&lines_parser, tokens.iter().cloned()) 730 | .output 731 | .expect("Failed to parse preprocessor tokens") 732 | .0; 733 | 734 | // remove empty lines 735 | lines_result 736 | .into_iter() 737 | .filter(|line| line.is_empty() == false) 738 | .collect() 739 | } 740 | pub fn preprocess(&self, lines: &[Box]) -> Vec> { 741 | let mut context = PreprocessorContext::new(); 742 | 743 | // preprocessed token stream 744 | let mut lines_token = Vec::new(); 745 | 746 | // preprocessing phase 747 | for line in lines.iter() { 748 | let line_token = line.emit(&mut context, self); 749 | if line_token.is_empty() == false { 750 | lines_token.push(line_token); 751 | } 752 | } 753 | 754 | // check errors 755 | if context.if_stack.is_empty() == false { 756 | panic!("#if block is not closed"); 757 | } 758 | 759 | // change Ident to keyword token 760 | let ident_to_keyword = ident_to_keyword_map(); 761 | for line in lines_token.iter_mut() { 762 | for token in line.iter_mut() { 763 | if let Token::Identifier(name) = token { 764 | if let Some(replace_token) = ident_to_keyword.get(name) { 765 | *token = replace_token.clone(); 766 | } 767 | } 768 | } 769 | } 770 | 771 | lines_token 772 | } 773 | 774 | /// replace macro in given tokens 775 | /// this is not recursive macro replacement 776 | /// returns true if there was any replacement occured 777 | pub fn replace(&self, src_tokens: &[Token], ctx: &PreprocessorContext) -> (bool, Vec) { 778 | let mut tokens = Vec::new(); 779 | let mut it = src_tokens.iter().cloned(); 780 | 781 | let mut replaced = false; 782 | while let Some(token) = it.next() { 783 | match token { 784 | // check if it is macro 785 | Token::Identifier(name) => { 786 | let macro_data = ctx.define_map.get(&name); 787 | if let Some(MacroData::DirectReplace(replacement)) = macro_data { 788 | // identifier links to normal macro 789 | let mut replacement = replacement.clone(); 790 | tokens.append(&mut replacement); 791 | replaced = true; 792 | } else if let Some(MacroData::Function(param_count, replacement)) = macro_data { 793 | // identifier links to function-like macro 794 | // check arguments 795 | let parser = rp::seq!( 796 | rp::one(Token::LeftParen).void().or_else(|| -> () { 797 | panic!("LeftParen '(' expected for macro call {}", name); 798 | }), 799 | self.macro_argument_item_list 800 | .clone() 801 | .or_else(|| -> Vec> { 802 | panic!("Invalid arguments for macro {}", name); 803 | }), 804 | rp::one(Token::RightParen).void().or_else(|| -> () { 805 | panic!("RightParen ')' expected for macro call {}", name); 806 | }) 807 | ); 808 | let args_res = rp::parse(&parser, it); 809 | if let Some((args,)) = args_res.output { 810 | if args.len() != *param_count { 811 | panic!("Invalid number of arguments for macro {}", name); 812 | } 813 | 814 | for replacement_token in replacement.iter() { 815 | if let Token::PreprocessorPlaceholder(arg_idx) = replacement_token { 816 | tokens.append(&mut args[*arg_idx].clone()); 817 | } else { 818 | tokens.push(replacement_token.clone()); 819 | } 820 | } 821 | } else { 822 | panic!("Invalid arguments for macro {}", name); 823 | } 824 | it = args_res.it; 825 | replaced = true; 826 | } else { 827 | tokens.push(Token::Identifier(name)); 828 | } 829 | } 830 | _ => { 831 | tokens.push(token); 832 | } 833 | } 834 | } 835 | 836 | (replaced, tokens) 837 | } 838 | /// replace macro in given tokens 839 | /// this is recursive macro replacement 840 | pub fn replace_recursive(&self, src_tokens: &[Token], ctx: &PreprocessorContext) -> Vec { 841 | let mut tokens = src_tokens.to_vec(); 842 | loop { 843 | let (replaced, new_tokens) = self.replace(&tokens, ctx); 844 | if replaced == false { 845 | break new_tokens; 846 | } 847 | tokens = new_tokens; 848 | } 849 | } 850 | } 851 | -------------------------------------------------------------------------------- /src/preprocess/preprocessor.rs: -------------------------------------------------------------------------------- 1 | use rusty_parser as rp; 2 | 3 | use std::fmt::Debug; 4 | use std::vec::Vec; 5 | 6 | use crate::token::Token; 7 | 8 | use super::context::*; 9 | use super::parser::PreprocessorParser; 10 | 11 | pub trait PreprocessedTokenLine: Debug { 12 | fn emit(&self, ctx: &mut PreprocessorContext, parser: &PreprocessorParser) -> Vec; 13 | 14 | fn is_empty(&self) -> bool { 15 | false 16 | } 17 | } 18 | 19 | #[derive(Debug)] 20 | pub struct Define { 21 | pub name: String, 22 | pub replacement: Vec, 23 | } 24 | impl PreprocessedTokenLine for Define { 25 | fn emit(&self, ctx: &mut PreprocessorContext, _parser: &PreprocessorParser) -> Vec { 26 | if ctx.should_emit() == false { 27 | return Vec::new(); 28 | } 29 | let old = ctx.define_map.insert( 30 | self.name.clone(), 31 | MacroData::DirectReplace(self.replacement.clone()), 32 | ); 33 | if old.is_some() { 34 | panic!("Macro {} is already defined", self.name); 35 | } 36 | Vec::new() 37 | } 38 | } 39 | 40 | #[derive(Debug)] 41 | pub struct DefineFunction { 42 | pub name: String, 43 | pub param_count: usize, 44 | pub replacement: Vec, 45 | } 46 | impl PreprocessedTokenLine for DefineFunction { 47 | fn emit(&self, ctx: &mut PreprocessorContext, _parser: &PreprocessorParser) -> Vec { 48 | if ctx.should_emit() == false { 49 | return Vec::new(); 50 | } 51 | 52 | let old = ctx.define_map.insert( 53 | self.name.clone(), 54 | MacroData::Function(self.param_count, self.replacement.clone()), 55 | ); 56 | if old.is_some() { 57 | panic!("Macro {} is already defined", self.name); 58 | } 59 | Vec::new() 60 | } 61 | } 62 | 63 | #[derive(Debug)] 64 | pub struct IfDef { 65 | pub name: String, 66 | } 67 | impl PreprocessedTokenLine for IfDef { 68 | fn emit(&self, ctx: &mut PreprocessorContext, _parser: &PreprocessorParser) -> Vec { 69 | if ctx.should_emit() == false { 70 | return Vec::new(); 71 | } 72 | 73 | if ctx.define_map.contains_key(&self.name) { 74 | ctx.if_stack.push(IfStackData { 75 | processed: true, 76 | current: true, 77 | }); 78 | } else { 79 | ctx.if_stack.push(IfStackData { 80 | processed: false, 81 | current: false, 82 | }); 83 | } 84 | Vec::new() 85 | } 86 | } 87 | #[derive(Debug)] 88 | pub struct IfNDef { 89 | pub name: String, 90 | } 91 | impl PreprocessedTokenLine for IfNDef { 92 | fn emit(&self, ctx: &mut PreprocessorContext, _parser: &PreprocessorParser) -> Vec { 93 | if ctx.should_emit() == false { 94 | return Vec::new(); 95 | } 96 | 97 | if ctx.define_map.contains_key(&self.name) { 98 | ctx.if_stack.push(IfStackData { 99 | processed: false, 100 | current: false, 101 | }); 102 | } else { 103 | ctx.if_stack.push(IfStackData { 104 | processed: true, 105 | current: true, 106 | }); 107 | } 108 | Vec::new() 109 | } 110 | } 111 | #[derive(Debug)] 112 | pub struct Else {} 113 | impl PreprocessedTokenLine for Else { 114 | fn emit(&self, ctx: &mut PreprocessorContext, _parser: &PreprocessorParser) -> Vec { 115 | let branch_data = ctx.if_stack.last_mut().expect("#else without #if"); 116 | if branch_data.current { 117 | branch_data.current = false; 118 | } else if branch_data.processed == false { 119 | branch_data.processed = true; 120 | branch_data.current = true; 121 | } 122 | Vec::new() 123 | } 124 | } 125 | #[derive(Debug)] 126 | pub struct EndIf {} 127 | impl PreprocessedTokenLine for EndIf { 128 | fn emit(&self, ctx: &mut PreprocessorContext, _parser: &PreprocessorParser) -> Vec { 129 | ctx.if_stack.pop().expect("#endif without #if"); 130 | Vec::new() 131 | } 132 | } 133 | 134 | #[derive(Debug)] 135 | pub struct If { 136 | pub expression_tokens: Vec, 137 | } 138 | impl PreprocessedTokenLine for If { 139 | fn emit(&self, ctx: &mut PreprocessorContext, parser: &PreprocessorParser) -> Vec { 140 | let tokens = parser.replace_recursive(&self.expression_tokens, ctx); 141 | let expression = rp::parse(&parser.expression, tokens.iter().cloned()) 142 | .output 143 | .expect("Failed to parse expression") 144 | .0; 145 | 146 | let val = expression.eval(ctx); 147 | if ctx.should_emit() == false { 148 | return Vec::new(); 149 | } 150 | 151 | if val != 0 { 152 | ctx.if_stack.push(IfStackData { 153 | processed: true, 154 | current: true, 155 | }); 156 | } else { 157 | ctx.if_stack.push(IfStackData { 158 | processed: false, 159 | current: false, 160 | }); 161 | } 162 | Vec::new() 163 | } 164 | } 165 | #[derive(Debug)] 166 | pub struct ElIf { 167 | pub expression_tokens: Vec, 168 | } 169 | impl PreprocessedTokenLine for ElIf { 170 | fn emit(&self, ctx: &mut PreprocessorContext, parser: &PreprocessorParser) -> Vec { 171 | let tokens = parser.replace_recursive(&self.expression_tokens, ctx); 172 | let expression = rp::parse(&parser.expression, tokens.iter().cloned()) 173 | .output 174 | .expect("Failed to parse expression") 175 | .0; 176 | 177 | let val = expression.eval(ctx); 178 | let branch_data = ctx.if_stack.last_mut().expect("#else without #if"); 179 | 180 | if val == 0 { 181 | branch_data.current = false; 182 | } else { 183 | if branch_data.current { 184 | branch_data.current = false; 185 | } else if branch_data.processed == false { 186 | branch_data.processed = true; 187 | branch_data.current = true; 188 | } 189 | } 190 | 191 | Vec::new() 192 | } 193 | } 194 | 195 | #[derive(Debug)] 196 | pub struct Undef { 197 | pub name: String, 198 | } 199 | impl PreprocessedTokenLine for Undef { 200 | fn emit(&self, ctx: &mut PreprocessorContext, _parser: &PreprocessorParser) -> Vec { 201 | if ctx.should_emit() == false { 202 | return Vec::new(); 203 | } 204 | 205 | let old = ctx.define_map.remove(&self.name); 206 | if old.is_none() { 207 | panic!("Macro {} is not defined", self.name); 208 | } 209 | Vec::new() 210 | } 211 | } 212 | 213 | #[derive(Debug)] 214 | pub struct RawTokens { 215 | pub tokens: Vec, 216 | } 217 | impl PreprocessedTokenLine for RawTokens { 218 | fn emit(&self, ctx: &mut PreprocessorContext, parser: &PreprocessorParser) -> Vec { 219 | if ctx.should_emit() == false { 220 | return Vec::new(); 221 | } 222 | 223 | // replace macro to real tokens here 224 | parser.replace_recursive(&self.tokens, ctx) 225 | } 226 | 227 | fn is_empty(&self) -> bool { 228 | self.tokens.is_empty() 229 | } 230 | } 231 | -------------------------------------------------------------------------------- /src/token/character.rs: -------------------------------------------------------------------------------- 1 | use super::token::DynParser; 2 | use super::token::Token; 3 | use rusty_parser as rp; 4 | 5 | use rp::IntoParser; 6 | 7 | pub fn char_literal_parser() -> DynParser { 8 | // char literal enclosed with ' ' 9 | let escape = rp::or!( 10 | 'n'.output('\n'), 11 | 't'.output('\t'), 12 | '\\'.output('\\'), 13 | '\''.output('\''), 14 | '"'.output('"') 15 | ); 16 | let escape = rp::seq!('\\'.void(), escape); 17 | let char_literal = rp::seq!( 18 | '\''.void(), 19 | rp::or!(escape, rp::any().not('\'')), 20 | '\''.void() 21 | ); 22 | DynParser::new(char_literal.map(|c: char| Token::ConstantCharacter((c as u8) as i8))) 23 | } 24 | -------------------------------------------------------------------------------- /src/token/identifier.rs: -------------------------------------------------------------------------------- 1 | use super::token::DynParser; 2 | use super::token::Token; 3 | use rusty_parser as rp; 4 | 5 | use rp::IntoParser; 6 | 7 | pub fn identifier_parser() -> DynParser { 8 | let digit = ('0'..='9').void(); 9 | let alpha = rp::or!('a'..='z', 'A'..='Z').void(); 10 | let identifier = rp::seq!( 11 | rp::or!(alpha, '_'.void()), 12 | rp::or!(alpha, digit, '_'.void()).repeat(0..) 13 | ) 14 | .string(); 15 | 16 | DynParser::new(identifier.map(|s: String| Token::Identifier(s))) 17 | } 18 | -------------------------------------------------------------------------------- /src/token/mod.rs: -------------------------------------------------------------------------------- 1 | pub(crate) mod character; 2 | pub(crate) mod identifier; 3 | pub(crate) mod numeric; 4 | pub(crate) mod string; 5 | pub(crate) mod token; 6 | pub(crate) mod tokenize; 7 | pub(crate) mod trie; 8 | 9 | pub use token::Token; 10 | -------------------------------------------------------------------------------- /src/token/numeric.rs: -------------------------------------------------------------------------------- 1 | use super::token::DynParser; 2 | use super::token::Token; 3 | use rusty_parser as rp; 4 | 5 | use rp::IntoParser; 6 | 7 | /* 8 | D [0-9] 9 | H [0-9a-fA-F] 10 | IS (u|U|l|L)* 11 | 12 | 0[xX]{H}+{IS}? { count(); return(CONSTANT); } 13 | 0{D}+{IS}? { count(); return(CONSTANT); } 14 | {D}+{IS}? { count(); return(CONSTANT); } 15 | */ 16 | pub fn integer_numeric_parser() -> DynParser { 17 | let digit = ('0'..='9').into_parser(); 18 | let hex_low = ('a'..='f').into_parser(); 19 | let hex_up = ('A'..='F').into_parser(); 20 | 21 | let dec = digit; 22 | let oct = ('0'..='7').into_parser(); 23 | let hex = rp::or!(digit, hex_low, hex_up); 24 | 25 | let dec_int = rp::seq('1'..='9', dec.repeat(0..)).void(); 26 | 27 | let oct_int = rp::seq('0', oct.repeat(0..)).void(); 28 | 29 | let hex_int = rp::seq!("0x", hex.repeat(1..)).void(); 30 | 31 | let integer_numeric = rp::or!(hex_int, oct_int, dec_int); 32 | 33 | let suffix = rp::or!('u', 'U', 'l', 'L'); 34 | 35 | let integer_numeric = rp::seq!(integer_numeric.string(), suffix.optional()); 36 | 37 | DynParser::new(integer_numeric.map(|s: String, suffix: Option| { 38 | let parse_res = s.parse::().expect("Failed to parse String to u64"); 39 | let suffix = suffix.or(Some('+')).unwrap(); 40 | match suffix { 41 | 'u' | 'U' => Token::ConstantUnsignedInteger(parse_res as u32), 42 | 'l' | 'L' => Token::ConstantLong(parse_res as i64), 43 | _ => Token::ConstantInteger(parse_res as i32), 44 | } 45 | })) 46 | } 47 | 48 | /* 49 | D [0-9] 50 | E [Ee][+-]?{D}+ 51 | FS (f|F|l|L) 52 | 53 | {D}+{E}{FS}? { count(); return(CONSTANT); } 54 | {D}*"."{D}+({E})?{FS}? { count(); return(CONSTANT); } 55 | {D}+"."{D}*({E})?{FS}? { count(); return(CONSTANT); } 56 | */ 57 | 58 | pub fn float_numeric_parser() -> DynParser { 59 | let digit = ('0'..='9').into_parser(); 60 | 61 | let exp = rp::seq!( 62 | rp::or!('e', 'E'), 63 | rp::or!('+', '-').optional(), 64 | digit.repeat(1..) 65 | ); 66 | 67 | let suffix = rp::or!('f', 'F', 'l', 'L').optional(); 68 | 69 | let case1 = rp::seq!(digit.repeat(1..), exp); 70 | let case2 = rp::seq!(digit.repeat(0..), '.', digit.repeat(1..), exp.optional()); 71 | let case3 = rp::seq!(digit.repeat(1..), '.', digit.repeat(0..), exp.optional()); 72 | 73 | let float_numeric = rp::or!(case1.void(), case2.void(), case3.void()); 74 | let float_numeric = rp::seq!(float_numeric.string(), suffix); 75 | 76 | DynParser::new(float_numeric.map(|s: String, suffix: Option| { 77 | let parse_res: f64 = s.parse::().expect("Failed to parse String to f64"); 78 | let suffix = suffix.or(Some('f')).unwrap(); 79 | match suffix { 80 | 'f' | 'F' => Token::ConstantFloat(parse_res as f32), 81 | 'l' | 'L' => Token::ConstantDouble(parse_res), 82 | _ => panic!("Invalid suffix for float"), 83 | } 84 | })) 85 | } 86 | -------------------------------------------------------------------------------- /src/token/string.rs: -------------------------------------------------------------------------------- 1 | use super::token::DynParser; 2 | use super::token::Token; 3 | use rusty_parser as rp; 4 | 5 | use rp::IntoParser; 6 | 7 | pub fn string_literal_parser() -> DynParser { 8 | // char literal enclosed with " " 9 | // this is a bit different from the char literal 10 | let escape = rp::or!( 11 | 'n'.output('\n'), 12 | 't'.output('\t'), 13 | '\\'.output('\\'), 14 | '\''.output('\''), 15 | '"'.output('"') 16 | ); 17 | let escape = rp::seq!('\\'.void(), escape); 18 | let one_char = rp::or!(escape, rp::any().not('"')); 19 | 20 | let string_literal = rp::seq!( 21 | '"'.void(), 22 | one_char 23 | .repeat(0..) 24 | .map(|v: Vec| v.into_iter().collect::()), 25 | '"'.void() 26 | ); 27 | 28 | DynParser::new(string_literal.map(|s: String| Token::StringLiteral(s))) 29 | } 30 | -------------------------------------------------------------------------------- /src/token/token.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, PartialEq, Clone)] 2 | pub enum Token { 3 | Others(char), // any other character that failed to parse; 4 | Identifier(String), 5 | ConstantCharacter(i8), 6 | ConstantInteger(i32), 7 | ConstantLong(i64), 8 | ConstantUnsignedInteger(u32), 9 | ConstantUnsignedLong(u64), 10 | ConstantFloat(f32), 11 | ConstantDouble(f64), 12 | StringLiteral(String), 13 | PreprocessorDefine, 14 | PreprocessorIfDef, 15 | PreprocessorIfNDef, 16 | PreprocessorEndIf, 17 | PreprocessorElIf, 18 | PreprocessorUndef, 19 | PreprocessorElse, 20 | PreprocessorPlaceholder(usize), // for function-like macro 21 | PreprocessorIf, 22 | PreprocessorInclude, 23 | NewLine, 24 | Auto, 25 | Break, 26 | Case, 27 | Char, 28 | Const, 29 | Continue, 30 | Default, 31 | Do, 32 | Double, 33 | Else, 34 | Enum, 35 | Extern, 36 | Float, 37 | For, 38 | Goto, 39 | If, 40 | Int, 41 | Long, 42 | Register, 43 | Return, 44 | Short, 45 | Signed, 46 | Sizeof, 47 | Static, 48 | Struct, 49 | Switch, 50 | Typedef, 51 | Union, 52 | Unsigned, 53 | Void, 54 | Volatile, 55 | While, 56 | Ellipsis, // ... 57 | RightAssign, 58 | LeftAssign, 59 | AddAssign, 60 | SubAssign, 61 | MulAssign, 62 | DivAssign, 63 | ModAssign, 64 | AndAssign, 65 | XorAssign, 66 | OrAssign, 67 | RightOp, 68 | LeftOp, 69 | IncOp, 70 | DecOp, 71 | PtrOp, 72 | AndOp, 73 | OrOp, 74 | LeOp, 75 | GeOp, 76 | EqOp, 77 | NeOp, 78 | SemiColon, 79 | LeftBrace, 80 | RightBrace, 81 | Comma, 82 | Colon, 83 | Equal, 84 | LeftParen, 85 | RightParen, 86 | LeftBracket, 87 | RightBracket, 88 | Dot, 89 | Ampersand, 90 | Exclamation, 91 | Tilde, 92 | Minus, 93 | Plus, 94 | Star, 95 | Slash, 96 | Percent, 97 | LessThan, 98 | GreaterThan, 99 | Caret, 100 | Pipe, 101 | Question, 102 | Whitespace, // one or more whitespaces 103 | } 104 | 105 | use rusty_parser as rp; 106 | 107 | pub type DynParser = rp::DynBoxChars<(Token,)>; 108 | -------------------------------------------------------------------------------- /src/token/tokenize.rs: -------------------------------------------------------------------------------- 1 | use super::character; 2 | use super::identifier; 3 | use super::numeric; 4 | use super::string; 5 | use super::token::Token; 6 | use super::trie; 7 | use rusty_parser as rp; 8 | 9 | use rp::IntoParser; 10 | 11 | /// Tokenize the raw source code into a list of tokens 12 | /// This phase will remove c/cpp comments 13 | /// sequence of whitespaces will be combined into one Token::Whitespace 14 | /// the newline '\n' will be kept as a Token::NewLine for later phase 15 | /// If the source is not end with '\n', it will be added automatically 16 | pub fn tokenize(source: &str) -> Vec { 17 | // c++ comment 18 | let cpp_comment = rp::seq!( 19 | "//", 20 | rp::any().not('\n').repeat(0..), 21 | rp::or!(rp::end(), '\n'.void()).not_consume() 22 | ) 23 | .void(); 24 | 25 | // c comment 26 | let c_comment = rp::seq!("/*", rp::any().not("*/").repeat(0..), "*/").void(); 27 | 28 | let ignore_all = rp::or!(cpp_comment, c_comment).void().repeat(0..); 29 | let whitespace = rp::or!(' '.void(), '\t'.void(), '\r'.void(), "\\\n".void()); 30 | 31 | let char_literal = character::char_literal_parser(); 32 | let string_literal = string::string_literal_parser(); 33 | let identifier = identifier::identifier_parser(); 34 | let integer_numeric = numeric::integer_numeric_parser(); 35 | let float_numeric = numeric::float_numeric_parser(); 36 | let trie = trie::keyword_parser(); 37 | 38 | // parse keyword as identifier first 39 | let one_token = rp::or!( 40 | trie, 41 | identifier, 42 | string_literal, 43 | char_literal, 44 | float_numeric, 45 | integer_numeric, 46 | whitespace.repeat(1..).void().map(|| Token::Whitespace), 47 | rp::any().map(|c| Token::Others(c)) 48 | ); 49 | 50 | let multiple_tokens = rp::seq!(ignore_all, rp::seq!(one_token, ignore_all).repeat(0..)); 51 | 52 | let file_parser = rp::seq!(multiple_tokens, rp::end()); 53 | let res = rp::parse(&file_parser, source.chars()); 54 | let mut res = res.output.expect("Failed to Tokenize").0; 55 | if res.last() != Some(&Token::NewLine) { 56 | res.push(Token::NewLine); 57 | } 58 | 59 | res 60 | } 61 | -------------------------------------------------------------------------------- /src/token/trie.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | use super::token::Token; 4 | use rusty_parser as rp; 5 | 6 | pub fn keyword_parser() -> rp::DictHashMap<(Token,), char> { 7 | let mut dict = rp::DictHashMap::new(); 8 | 9 | dict.insert("...".chars(), (Token::Ellipsis,)); 10 | dict.insert(">>=".chars(), (Token::RightAssign,)); 11 | dict.insert("<<=".chars(), (Token::LeftAssign,)); 12 | dict.insert("+=".chars(), (Token::AddAssign,)); 13 | dict.insert("-=".chars(), (Token::SubAssign,)); 14 | dict.insert("*=".chars(), (Token::MulAssign,)); 15 | dict.insert("/=".chars(), (Token::DivAssign,)); 16 | dict.insert("%=".chars(), (Token::ModAssign,)); 17 | dict.insert("&=".chars(), (Token::AndAssign,)); 18 | dict.insert("^=".chars(), (Token::XorAssign,)); 19 | dict.insert("|=".chars(), (Token::OrAssign,)); 20 | dict.insert(">>".chars(), (Token::RightOp,)); 21 | dict.insert("<<".chars(), (Token::LeftOp,)); 22 | dict.insert("++".chars(), (Token::IncOp,)); 23 | dict.insert("--".chars(), (Token::DecOp,)); 24 | dict.insert("->".chars(), (Token::PtrOp,)); 25 | dict.insert("&&".chars(), (Token::AndOp,)); 26 | dict.insert("||".chars(), (Token::OrOp,)); 27 | dict.insert("<=".chars(), (Token::LeOp,)); 28 | dict.insert(">=".chars(), (Token::GeOp,)); 29 | dict.insert("==".chars(), (Token::EqOp,)); 30 | dict.insert("!=".chars(), (Token::NeOp,)); 31 | 32 | dict.insert(";".chars(), (Token::SemiColon,)); 33 | dict.insert("{".chars(), (Token::LeftBrace,)); 34 | dict.insert("<%".chars(), (Token::LeftBrace,)); 35 | dict.insert("}".chars(), (Token::RightBrace,)); 36 | dict.insert("%>".chars(), (Token::RightBrace,)); 37 | dict.insert(",".chars(), (Token::Comma,)); 38 | dict.insert(":".chars(), (Token::Colon,)); 39 | dict.insert("=".chars(), (Token::Equal,)); 40 | dict.insert("(".chars(), (Token::LeftParen,)); 41 | dict.insert(")".chars(), (Token::RightParen,)); 42 | dict.insert("[".chars(), (Token::LeftBracket,)); 43 | dict.insert("<:".chars(), (Token::LeftBracket,)); 44 | dict.insert("]".chars(), (Token::RightBracket,)); 45 | dict.insert(":>".chars(), (Token::RightBracket,)); 46 | dict.insert(".".chars(), (Token::Dot,)); 47 | dict.insert("&".chars(), (Token::Ampersand,)); 48 | dict.insert("!".chars(), (Token::Exclamation,)); 49 | dict.insert("~".chars(), (Token::Tilde,)); 50 | dict.insert("-".chars(), (Token::Minus,)); 51 | dict.insert("+".chars(), (Token::Plus,)); 52 | dict.insert("*".chars(), (Token::Star,)); 53 | dict.insert("/".chars(), (Token::Slash,)); 54 | dict.insert("%".chars(), (Token::Percent,)); 55 | dict.insert("<".chars(), (Token::LessThan,)); 56 | dict.insert(">".chars(), (Token::GreaterThan,)); 57 | dict.insert("^".chars(), (Token::Caret,)); 58 | dict.insert("|".chars(), (Token::Pipe,)); 59 | dict.insert("?".chars(), (Token::Question,)); 60 | dict.insert("#define".chars(), (Token::PreprocessorDefine,)); 61 | dict.insert("#ifdef".chars(), (Token::PreprocessorIfDef,)); 62 | dict.insert("#ifndef".chars(), (Token::PreprocessorIfNDef,)); 63 | dict.insert("#undef".chars(), (Token::PreprocessorUndef,)); 64 | dict.insert("#elif".chars(), (Token::PreprocessorElIf,)); 65 | dict.insert("#endif".chars(), (Token::PreprocessorEndIf,)); 66 | dict.insert("#else".chars(), (Token::PreprocessorElse,)); 67 | dict.insert("#if".chars(), (Token::PreprocessorIf,)); 68 | dict.insert("#include".chars(), (Token::PreprocessorInclude,)); 69 | dict.insert("\n".chars(), (Token::NewLine,)); 70 | 71 | dict 72 | } 73 | 74 | pub fn ident_to_keyword_map() -> HashMap { 75 | let mut dict = HashMap::new(); 76 | 77 | dict.insert("auto".to_string(), Token::Auto); 78 | dict.insert("break".to_string(), Token::Break); 79 | dict.insert("case".to_string(), Token::Case); 80 | dict.insert("char".to_string(), Token::Char); 81 | dict.insert("const".to_string(), Token::Const); 82 | dict.insert("continue".to_string(), Token::Continue); 83 | dict.insert("default".to_string(), Token::Default); 84 | dict.insert("do".to_string(), Token::Do); 85 | dict.insert("double".to_string(), Token::Double); 86 | dict.insert("else".to_string(), Token::Else); 87 | dict.insert("enum".to_string(), Token::Enum); 88 | dict.insert("extern".to_string(), Token::Extern); 89 | dict.insert("float".to_string(), Token::Float); 90 | dict.insert("for".to_string(), Token::For); 91 | dict.insert("goto".to_string(), Token::Goto); 92 | dict.insert("if".to_string(), Token::If); 93 | dict.insert("int".to_string(), Token::Int); 94 | dict.insert("long".to_string(), Token::Long); 95 | dict.insert("register".to_string(), Token::Register); 96 | dict.insert("return".to_string(), Token::Return); 97 | dict.insert("short".to_string(), Token::Short); 98 | dict.insert("signed".to_string(), Token::Signed); 99 | dict.insert("sizeof".to_string(), Token::Sizeof); 100 | dict.insert("static".to_string(), Token::Static); 101 | dict.insert("struct".to_string(), Token::Struct); 102 | dict.insert("switch".to_string(), Token::Switch); 103 | dict.insert("typedef".to_string(), Token::Typedef); 104 | dict.insert("union".to_string(), Token::Union); 105 | dict.insert("unsigned".to_string(), Token::Unsigned); 106 | dict.insert("void".to_string(), Token::Void); 107 | dict.insert("volatile".to_string(), Token::Volatile); 108 | dict.insert("while".to_string(), Token::While); 109 | 110 | dict 111 | } 112 | -------------------------------------------------------------------------------- /src/virtualmachine/function.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/virtualmachine/instruction/generation.rs: -------------------------------------------------------------------------------- 1 | use super::DefineLabel; 2 | use super::Instruction; 3 | use crate::ast::typename::TypeInfo; 4 | use crate::virtualmachine::scope::*; 5 | use std::collections::HashMap; 6 | 7 | #[derive(Debug, Clone)] 8 | pub struct FunctionInfo { 9 | pub return_type: TypeInfo, 10 | pub params: Vec<(Option, TypeInfo)>, 11 | pub is_defined: bool, 12 | } 13 | 14 | /// return type for search_variable by name 15 | #[derive(Debug, Clone, Copy)] 16 | pub enum VariableOffset { 17 | Global(usize), // absolute address in stack 18 | Local(isize), // relative address from rbp 19 | } 20 | 21 | #[derive(Debug)] 22 | pub struct InstructionGenerator { 23 | /// generated instructions 24 | pub instructions: Vec, 25 | 26 | /// function map 27 | pub functions: HashMap, 28 | /// label map 29 | pub labels: HashMap, 30 | /// for label, anonymous name generation 31 | pub unique_id: usize, 32 | /// label stack for continue, break 33 | /// default, break for switch statement 34 | pub label_stack: Vec<(String, String)>, 35 | 36 | /// global variables must have absolute address in stack 37 | /// local variables have relative address from rbp 38 | pub global_scope: Scope, 39 | 40 | /// function may have multiple scopes inside. 41 | /// we have to count the number of variable declaration 42 | /// for stack allocation 43 | pub function_scope: Option, 44 | /// local variable scopes 45 | pub scopes: Vec, 46 | 47 | /// start address of program 48 | pub start_address: usize, 49 | 50 | /// where constant data is stored 51 | /// for same-address system with stack data, it will be merged into stack upon program execution 52 | /// 53 | /// commonly, this is used for read-only data 54 | /// but we don't have `const` qualifier yet 55 | /// so it is mutable ... 56 | pub text_section: Vec, 57 | } 58 | impl InstructionGenerator { 59 | pub fn new() -> Self { 60 | Self { 61 | instructions: Vec::new(), 62 | functions: HashMap::new(), 63 | labels: HashMap::new(), 64 | unique_id: 0, 65 | start_address: 0, 66 | scopes: Vec::new(), 67 | function_scope: None, 68 | global_scope: Scope::new(), 69 | label_stack: Vec::new(), 70 | text_section: Vec::new(), 71 | } 72 | } 73 | /// push new instruction 74 | pub fn push(&mut self, instruction: Instruction) { 75 | self.instructions.push(instruction); 76 | } 77 | 78 | /// for unique label generation 79 | pub fn get_unique_id(&mut self) -> usize { 80 | let ret = self.unique_id; 81 | self.unique_id += 1; 82 | ret 83 | } 84 | /// for unique label generation 85 | pub fn get_unique_label(&mut self) -> String { 86 | format!(".__L{}__", self.get_unique_id()) 87 | } 88 | 89 | /// make new variable scopes 90 | pub fn push_scope(&mut self) { 91 | self.scopes.push(Scope::default()); 92 | } 93 | /// pop variable scopes 94 | pub fn pop_scope(&mut self) { 95 | self.scopes.pop().expect("pop_scope: no scope"); 96 | } 97 | 98 | /// make new named variable on current scope 99 | /// this does not allocate stack memory, just for variable counting 100 | pub fn declare_variable(&mut self, name: &str, type_info: &TypeInfo, count: usize) { 101 | let type_info = self.get_true_typeinfo(type_info); 102 | // if there is function scope, it is local variable 103 | let (offset, scope) = if let Some(func_scope) = &mut self.function_scope { 104 | let offset = func_scope.declared_variable_count; 105 | func_scope.declared_variable_count += count; 106 | 107 | func_scope.max_variable_count = func_scope 108 | .max_variable_count 109 | .max(func_scope.declared_variable_count); 110 | 111 | (offset, self.scopes.last_mut().unwrap()) 112 | } else { 113 | // if there is no function scope, it is global variable 114 | let len = self.global_scope.variables.len(); 115 | (len, &mut self.global_scope) 116 | }; 117 | let old = scope 118 | .variables 119 | .insert(name.to_string(), (type_info, offset as isize)); 120 | if let Some(_) = old { 121 | panic!("variable {} is already declared", name); 122 | } 123 | scope.declared_variable_count += count; 124 | } 125 | /// if variable's data is already in stack (e.g. function arguments) 126 | /// this deos not count up variable_count 127 | /// only for stack address-variable mapping 128 | pub fn link_variable(&mut self, name: &str, type_info: &TypeInfo, offset_from_rbp: isize) { 129 | let type_info = self.get_true_typeinfo(type_info); 130 | let scope = self.scopes.last_mut().unwrap(); 131 | let old = scope 132 | .variables 133 | .insert(name.to_string(), (type_info, offset_from_rbp)); 134 | if let Some(_) = old { 135 | panic!("variable {} is already declared", name); 136 | } 137 | } 138 | /// search variable by name across scopes 139 | pub fn search_variable(&self, name: &str) -> Option<(TypeInfo, VariableOffset)> { 140 | for scope in self.scopes.iter().rev() { 141 | if let Some((type_info, offset)) = scope.variables.get(name) { 142 | return Some(( 143 | self.get_true_typeinfo(type_info), 144 | VariableOffset::Local(*offset as isize), 145 | )); 146 | } 147 | } 148 | if let Some((type_info, offset)) = self.global_scope.variables.get(name) { 149 | return Some(( 150 | self.get_true_typeinfo(type_info), 151 | VariableOffset::Global(*offset as usize), 152 | )); 153 | } 154 | None 155 | } 156 | /// search typeinfo by name across scopes 157 | pub fn search_type(&self, name: &str) -> Option { 158 | for scope in self.scopes.iter().rev() { 159 | if let Some(type_info) = scope.type_infos.get(name) { 160 | return Some(self.get_true_typeinfo(type_info)); 161 | } 162 | } 163 | if let Some(type_info) = self.global_scope.type_infos.get(name) { 164 | return Some(self.get_true_typeinfo(type_info)); 165 | } 166 | None 167 | } 168 | /// for struct type (and typedef-ed type in future) 169 | /// there may be no field information in typeinfo ( `struct MyStruct a;` ) 170 | /// so we need to find the definition of struct 171 | pub fn get_true_typeinfo(&self, type_info: &TypeInfo) -> TypeInfo { 172 | match type_info { 173 | TypeInfo::Void 174 | | TypeInfo::UInt8 175 | | TypeInfo::UInt16 176 | | TypeInfo::UInt32 177 | | TypeInfo::UInt64 178 | | TypeInfo::Int8 179 | | TypeInfo::Int16 180 | | TypeInfo::Int32 181 | | TypeInfo::Int64 182 | | TypeInfo::Float32 183 | | TypeInfo::Float64 184 | | TypeInfo::Pointer(_) => type_info.clone(), 185 | TypeInfo::Array(t, len) => TypeInfo::Array(Box::new(self.get_true_typeinfo(t)), *len), 186 | TypeInfo::Const(t) => TypeInfo::Const(Box::new(self.get_true_typeinfo(t))), 187 | TypeInfo::Function(return_type, params) => { 188 | let mut new_params = Vec::new(); 189 | for t in params.iter() { 190 | new_params.push(self.get_true_typeinfo(t)); 191 | } 192 | TypeInfo::Function(Box::new(self.get_true_typeinfo(return_type)), new_params) 193 | } 194 | 195 | TypeInfo::Struct(sinfo) => { 196 | if sinfo.fields.is_some() { 197 | return type_info.clone(); 198 | } 199 | if sinfo.name.is_none() { 200 | panic!("get_true_typeinfo: anonymous struct"); 201 | } 202 | 203 | let searched = self.search_type(sinfo.name.as_ref().unwrap()).expect( 204 | format!( 205 | "get_true_typeinfo: struct {} is not defined", 206 | sinfo.name.as_ref().unwrap() 207 | ) 208 | .as_str(), 209 | ); 210 | if let TypeInfo::Struct(sinfo) = searched { 211 | return TypeInfo::Struct(sinfo.clone()); 212 | } else { 213 | panic!( 214 | "get_true_typeinfo: {} is not struct", 215 | sinfo.name.as_ref().unwrap() 216 | ); 217 | } 218 | } 219 | TypeInfo::Identifier(name) => self 220 | .search_type(name) 221 | .expect(format!("get_true_typeinfo: type {} is not defined", name).as_str()), 222 | _ => panic!("get_true_typeinfo: not implemented {:?}", type_info), 223 | } 224 | } 225 | 226 | /// link label name to current instruction address 227 | pub fn set_label(&mut self, label: &str) { 228 | let old = self 229 | .labels 230 | .insert(label.to_string(), self.instructions.len()); 231 | if let Some(_) = old { 232 | panic!("label {} is already defined", label); 233 | } 234 | self.push(Instruction::DefineLabel(DefineLabel { 235 | label: label.to_string(), 236 | })); 237 | } 238 | } 239 | -------------------------------------------------------------------------------- /src/virtualmachine/instruction/operand.rs: -------------------------------------------------------------------------------- 1 | use crate::virtualmachine::program::VirtualMachine; 2 | use crate::virtualmachine::variable::VariableData; 3 | 4 | /// Type for Operand 5 | /// Derefed: [rax + offset] 6 | /// Register: rax 7 | /// Value: constant value 8 | #[derive(Debug, Clone)] 9 | pub enum Operand { 10 | Derefed(usize, isize), // number of register 11 | Register(usize), // number of register 12 | Value(VariableData), 13 | } 14 | /// helper function 15 | pub(crate) fn get_operand_value<'a>( 16 | // helper function 17 | program: &'a VirtualMachine, 18 | operand: &'a Operand, 19 | ) -> &'a VariableData { 20 | match operand { 21 | Operand::Derefed(register, offset) => { 22 | &program.stack[(program.registers[*register].to_u64() as isize + *offset) as usize] 23 | } 24 | Operand::Register(register) => &program.registers[*register], 25 | Operand::Value(val) => val, 26 | } 27 | } 28 | /// helper function 29 | pub(crate) fn get_operand_value_mut<'a>( 30 | // helper function 31 | program: &'a mut VirtualMachine, 32 | operand: &'a Operand, 33 | ) -> &'a mut VariableData { 34 | match operand { 35 | Operand::Derefed(register, offset) => { 36 | &mut program.stack[(program.registers[*register].to_u64() as isize + *offset) as usize] 37 | } 38 | Operand::Register(register) => &mut program.registers[*register], 39 | Operand::Value(_) => { 40 | panic!("get_operand_value_mut: cannot get mutable reference from value") 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/virtualmachine/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod function; 2 | pub mod instruction; 3 | pub mod program; 4 | pub mod scope; 5 | pub mod variable; 6 | -------------------------------------------------------------------------------- /src/virtualmachine/program.rs: -------------------------------------------------------------------------------- 1 | use super::variable::VariableData; 2 | 3 | use crate::virtualmachine::instruction::generation::InstructionGenerator; 4 | use std::collections::HashMap; 5 | 6 | /// Virtual Program 7 | /// have stack, registers, labels 8 | pub struct VirtualMachine { 9 | pub label_map: HashMap, 10 | pub stack: Vec, 11 | 12 | /// size of text section 13 | /// because we use front of stack for text section, we need offset for stack pointer 14 | 15 | /// each register is for single primitive type 16 | /// rax, rbx, rcx, rdx, rtx, rbp, rsp 17 | /// last tree registers are for 18 | /// text section size, stack pointer and base pointer 19 | pub registers: [VariableData; 7], 20 | 21 | pub current_instruction: usize, 22 | } 23 | 24 | pub const STACK_SIZE: usize = 10240; // stack size 25 | pub const STACK_POINTER_REGISTER: usize = 6; // index of register for use as stack pointer (rsp) 26 | pub const STACK_POINTER_BASE_REGISTER: usize = 5; // index of register for use as stack base pointer (rbp) 27 | pub const TEXT_SIZE_REGISTER: usize = 4; // index of register for use as text section size (rtx) 28 | pub const RAX: usize = 0; // index of register for use as rax 29 | pub const RBX: usize = 1; // index of register for use as rax 30 | pub const RCX: usize = 2; // index of register for use as rax 31 | pub const RDX: usize = 3; // index of register for use as rax 32 | impl VirtualMachine { 33 | pub fn new() -> VirtualMachine { 34 | let mut ret = VirtualMachine { 35 | label_map: HashMap::new(), 36 | stack: Vec::new(), 37 | 38 | registers: [ 39 | VariableData::UInt64(0), // rax 40 | VariableData::UInt64(0), // rbx 41 | VariableData::UInt64(0), // rcx 42 | VariableData::UInt64(0), // rdx 43 | VariableData::UInt64(0), // rtx 44 | VariableData::UInt64(0), // rpb 45 | VariableData::UInt64(0), // rsp 46 | ], 47 | 48 | current_instruction: 0, 49 | }; 50 | // pre allocate stack 51 | ret.stack.resize(STACK_SIZE, VariableData::UInt64(0)); 52 | ret 53 | } 54 | 55 | pub fn execute(&mut self, instructions: &InstructionGenerator) { 56 | self.label_map = instructions.labels.clone(); 57 | self.current_instruction = instructions.start_address; 58 | 59 | // set base pointer and stack pointer 60 | self.registers[TEXT_SIZE_REGISTER] = 61 | VariableData::UInt64(instructions.text_section.len() as u64); 62 | self.registers[STACK_POINTER_REGISTER] = 63 | VariableData::UInt64(instructions.text_section.len() as u64); 64 | self.registers[STACK_POINTER_BASE_REGISTER] = 65 | VariableData::UInt64(instructions.text_section.len() as u64); 66 | 67 | // copy text data to front of the stack 68 | for (i, ch) in instructions.text_section.iter().enumerate() { 69 | self.stack[i] = VariableData::Int8(*ch as i8); 70 | } 71 | 72 | while self.current_instruction < instructions.instructions.len() { 73 | instructions.instructions[self.current_instruction].execute(self); 74 | 75 | self.current_instruction += 1; 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/virtualmachine/scope.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::typename::TypeInfo; 2 | use std::collections::HashMap; 3 | 4 | /// for variable scope 5 | #[derive(Default, Debug)] 6 | pub struct Scope { 7 | // for typedef & declaration 8 | pub type_infos: HashMap, 9 | 10 | // for variable declaration; (type, offset from rbp) 11 | pub variables: HashMap, 12 | 13 | pub declared_variable_count: usize, 14 | } 15 | impl Scope { 16 | pub fn new() -> Self { 17 | Self { 18 | type_infos: HashMap::new(), 19 | variables: HashMap::new(), 20 | declared_variable_count: 0, 21 | } 22 | } 23 | } 24 | 25 | /// scope for function 26 | /// this is not for variable mapping 27 | /// but for variable counting; to track the number of variables alive 28 | /// so need normal scope for variable declaration 29 | #[derive(Debug, Default)] 30 | pub struct FunctionScope { 31 | pub declared_variable_count: usize, 32 | pub max_variable_count: usize, 33 | } 34 | impl FunctionScope { 35 | pub fn new() -> Self { 36 | Self { 37 | declared_variable_count: 0, 38 | max_variable_count: 0, 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/virtualmachine/variable.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::typename::TypeInfo; 2 | 3 | #[derive(Debug, Clone)] 4 | pub enum VariableData { 5 | Int8(i8), 6 | Int16(i16), 7 | Int32(i32), 8 | Int64(i64), 9 | UInt8(u8), 10 | UInt16(u16), 11 | UInt32(u32), 12 | UInt64(u64), 13 | Float32(f32), 14 | Float64(f64), 15 | } 16 | 17 | impl Default for VariableData { 18 | fn default() -> Self { 19 | VariableData::Int32(0) 20 | } 21 | } 22 | 23 | impl VariableData { 24 | pub fn cast_to(&self, typeinfo: &TypeInfo) -> Option { 25 | match self { 26 | VariableData::UInt8(lu8) => match typeinfo { 27 | TypeInfo::UInt8 => Some(VariableData::UInt8(*lu8)), 28 | TypeInfo::UInt16 => Some(VariableData::UInt16(*lu8 as u16)), 29 | TypeInfo::UInt32 => Some(VariableData::UInt32(*lu8 as u32)), 30 | TypeInfo::UInt64 => Some(VariableData::UInt64(*lu8 as u64)), 31 | TypeInfo::Int8 => Some(VariableData::Int8(*lu8 as i8)), 32 | TypeInfo::Int16 => Some(VariableData::Int16(*lu8 as i16)), 33 | TypeInfo::Int32 => Some(VariableData::Int32(*lu8 as i32)), 34 | TypeInfo::Int64 => Some(VariableData::Int64(*lu8 as i64)), 35 | TypeInfo::Float32 => Some(VariableData::Float32(*lu8 as f32)), 36 | TypeInfo::Float64 => Some(VariableData::Float64(*lu8 as f64)), 37 | TypeInfo::Pointer(_) => Some(VariableData::UInt64(*lu8 as u64)), 38 | _ => None, 39 | }, 40 | VariableData::UInt16(lu16) => match typeinfo { 41 | TypeInfo::UInt8 => Some(VariableData::UInt8(*lu16 as u8)), 42 | TypeInfo::UInt16 => Some(VariableData::UInt16(*lu16)), 43 | TypeInfo::UInt32 => Some(VariableData::UInt32(*lu16 as u32)), 44 | TypeInfo::UInt64 => Some(VariableData::UInt64(*lu16 as u64)), 45 | TypeInfo::Int8 => Some(VariableData::Int8(*lu16 as i8)), 46 | TypeInfo::Int16 => Some(VariableData::Int16(*lu16 as i16)), 47 | TypeInfo::Int32 => Some(VariableData::Int32(*lu16 as i32)), 48 | TypeInfo::Int64 => Some(VariableData::Int64(*lu16 as i64)), 49 | TypeInfo::Float32 => Some(VariableData::Float32(*lu16 as f32)), 50 | TypeInfo::Float64 => Some(VariableData::Float64(*lu16 as f64)), 51 | TypeInfo::Pointer(_) => Some(VariableData::UInt64(*lu16 as u64)), 52 | _ => None, 53 | }, 54 | VariableData::UInt32(lu32) => match typeinfo { 55 | TypeInfo::UInt8 => Some(VariableData::UInt8(*lu32 as u8)), 56 | TypeInfo::UInt16 => Some(VariableData::UInt16(*lu32 as u16)), 57 | TypeInfo::UInt32 => Some(VariableData::UInt32(*lu32)), 58 | TypeInfo::UInt64 => Some(VariableData::UInt64(*lu32 as u64)), 59 | TypeInfo::Int8 => Some(VariableData::Int8(*lu32 as i8)), 60 | TypeInfo::Int16 => Some(VariableData::Int16(*lu32 as i16)), 61 | TypeInfo::Int32 => Some(VariableData::Int32(*lu32 as i32)), 62 | TypeInfo::Int64 => Some(VariableData::Int64(*lu32 as i64)), 63 | TypeInfo::Float32 => Some(VariableData::Float32(*lu32 as f32)), 64 | TypeInfo::Float64 => Some(VariableData::Float64(*lu32 as f64)), 65 | TypeInfo::Pointer(_) => Some(VariableData::UInt64(*lu32 as u64)), 66 | _ => None, 67 | }, 68 | VariableData::UInt64(lu64) => match typeinfo { 69 | TypeInfo::UInt8 => Some(VariableData::UInt8(*lu64 as u8)), 70 | TypeInfo::UInt16 => Some(VariableData::UInt16(*lu64 as u16)), 71 | TypeInfo::UInt32 => Some(VariableData::UInt32(*lu64 as u32)), 72 | TypeInfo::UInt64 => Some(VariableData::UInt64(*lu64)), 73 | TypeInfo::Int8 => Some(VariableData::Int8(*lu64 as i8)), 74 | TypeInfo::Int16 => Some(VariableData::Int16(*lu64 as i16)), 75 | TypeInfo::Int32 => Some(VariableData::Int32(*lu64 as i32)), 76 | TypeInfo::Int64 => Some(VariableData::Int64(*lu64 as i64)), 77 | TypeInfo::Float32 => Some(VariableData::Float32(*lu64 as f32)), 78 | TypeInfo::Float64 => Some(VariableData::Float64(*lu64 as f64)), 79 | TypeInfo::Pointer(_) => Some(VariableData::UInt64(*lu64 as u64)), 80 | _ => None, 81 | }, 82 | VariableData::Int8(li8) => match typeinfo { 83 | TypeInfo::UInt8 => Some(VariableData::UInt8(*li8 as u8)), 84 | TypeInfo::UInt16 => Some(VariableData::UInt16(*li8 as u16)), 85 | TypeInfo::UInt32 => Some(VariableData::UInt32(*li8 as u32)), 86 | TypeInfo::UInt64 => Some(VariableData::UInt64(*li8 as u64)), 87 | TypeInfo::Int8 => Some(VariableData::Int8(*li8)), 88 | TypeInfo::Int16 => Some(VariableData::Int16(*li8 as i16)), 89 | TypeInfo::Int32 => Some(VariableData::Int32(*li8 as i32)), 90 | TypeInfo::Int64 => Some(VariableData::Int64(*li8 as i64)), 91 | TypeInfo::Float32 => Some(VariableData::Float32(*li8 as f32)), 92 | TypeInfo::Float64 => Some(VariableData::Float64(*li8 as f64)), 93 | TypeInfo::Pointer(_) => Some(VariableData::UInt64(*li8 as u64)), 94 | _ => None, 95 | }, 96 | VariableData::Int16(li16) => match typeinfo { 97 | TypeInfo::UInt8 => Some(VariableData::UInt8(*li16 as u8)), 98 | TypeInfo::UInt16 => Some(VariableData::UInt16(*li16 as u16)), 99 | TypeInfo::UInt32 => Some(VariableData::UInt32(*li16 as u32)), 100 | TypeInfo::UInt64 => Some(VariableData::UInt64(*li16 as u64)), 101 | TypeInfo::Int8 => Some(VariableData::Int8(*li16 as i8)), 102 | TypeInfo::Int16 => Some(VariableData::Int16(*li16)), 103 | TypeInfo::Int32 => Some(VariableData::Int32(*li16 as i32)), 104 | TypeInfo::Int64 => Some(VariableData::Int64(*li16 as i64)), 105 | TypeInfo::Float32 => Some(VariableData::Float32(*li16 as f32)), 106 | TypeInfo::Float64 => Some(VariableData::Float64(*li16 as f64)), 107 | TypeInfo::Pointer(_) => Some(VariableData::UInt64(*li16 as u64)), 108 | _ => None, 109 | }, 110 | VariableData::Int32(li32) => match typeinfo { 111 | TypeInfo::UInt8 => Some(VariableData::UInt8(*li32 as u8)), 112 | TypeInfo::UInt16 => Some(VariableData::UInt16(*li32 as u16)), 113 | TypeInfo::UInt32 => Some(VariableData::UInt32(*li32 as u32)), 114 | TypeInfo::UInt64 => Some(VariableData::UInt64(*li32 as u64)), 115 | TypeInfo::Int8 => Some(VariableData::Int8(*li32 as i8)), 116 | TypeInfo::Int16 => Some(VariableData::Int16(*li32 as i16)), 117 | TypeInfo::Int32 => Some(VariableData::Int32(*li32)), 118 | TypeInfo::Int64 => Some(VariableData::Int64(*li32 as i64)), 119 | TypeInfo::Float32 => Some(VariableData::Float32(*li32 as f32)), 120 | TypeInfo::Float64 => Some(VariableData::Float64(*li32 as f64)), 121 | TypeInfo::Pointer(_) => Some(VariableData::UInt64(*li32 as u64)), 122 | _ => None, 123 | }, 124 | VariableData::Int64(li64) => match typeinfo { 125 | TypeInfo::UInt8 => Some(VariableData::UInt8(*li64 as u8)), 126 | TypeInfo::UInt16 => Some(VariableData::UInt16(*li64 as u16)), 127 | TypeInfo::UInt32 => Some(VariableData::UInt32(*li64 as u32)), 128 | TypeInfo::UInt64 => Some(VariableData::UInt64(*li64 as u64)), 129 | TypeInfo::Int8 => Some(VariableData::Int8(*li64 as i8)), 130 | TypeInfo::Int16 => Some(VariableData::Int16(*li64 as i16)), 131 | TypeInfo::Int32 => Some(VariableData::Int32(*li64 as i32)), 132 | TypeInfo::Int64 => Some(VariableData::Int64(*li64)), 133 | TypeInfo::Float32 => Some(VariableData::Float32(*li64 as f32)), 134 | TypeInfo::Float64 => Some(VariableData::Float64(*li64 as f64)), 135 | TypeInfo::Pointer(_) => Some(VariableData::UInt64(*li64 as u64)), 136 | _ => None, 137 | }, 138 | VariableData::Float32(lf32) => match typeinfo { 139 | TypeInfo::UInt8 => Some(VariableData::UInt8(*lf32 as u8)), 140 | TypeInfo::UInt16 => Some(VariableData::UInt16(*lf32 as u16)), 141 | TypeInfo::UInt32 => Some(VariableData::UInt32(*lf32 as u32)), 142 | TypeInfo::UInt64 => Some(VariableData::UInt64(*lf32 as u64)), 143 | TypeInfo::Int8 => Some(VariableData::Int8(*lf32 as i8)), 144 | TypeInfo::Int16 => Some(VariableData::Int16(*lf32 as i16)), 145 | TypeInfo::Int32 => Some(VariableData::Int32(*lf32 as i32)), 146 | TypeInfo::Int64 => Some(VariableData::Int64(*lf32 as i64)), 147 | TypeInfo::Float32 => Some(VariableData::Float32(*lf32)), 148 | TypeInfo::Float64 => Some(VariableData::Float64(*lf32 as f64)), 149 | _ => None, 150 | }, 151 | VariableData::Float64(lf64) => match typeinfo { 152 | TypeInfo::UInt8 => Some(VariableData::UInt8(*lf64 as u8)), 153 | TypeInfo::UInt16 => Some(VariableData::UInt16(*lf64 as u16)), 154 | TypeInfo::UInt32 => Some(VariableData::UInt32(*lf64 as u32)), 155 | TypeInfo::UInt64 => Some(VariableData::UInt64(*lf64 as u64)), 156 | TypeInfo::Int8 => Some(VariableData::Int8(*lf64 as i8)), 157 | TypeInfo::Int16 => Some(VariableData::Int16(*lf64 as i16)), 158 | TypeInfo::Int32 => Some(VariableData::Int32(*lf64 as i32)), 159 | TypeInfo::Int64 => Some(VariableData::Int64(*lf64 as i64)), 160 | TypeInfo::Float32 => Some(VariableData::Float32(*lf64 as f32)), 161 | TypeInfo::Float64 => Some(VariableData::Float64(*lf64)), 162 | _ => None, 163 | }, 164 | } 165 | } 166 | 167 | pub fn from_i64(i: i64, typeinfo: &TypeInfo) -> VariableData { 168 | match typeinfo { 169 | TypeInfo::Int8 => VariableData::Int8(i as i8), 170 | TypeInfo::Int16 => VariableData::Int16(i as i16), 171 | TypeInfo::Int32 => VariableData::Int32(i as i32), 172 | TypeInfo::Int64 => VariableData::Int64(i), 173 | TypeInfo::UInt8 => VariableData::UInt8(i as u8), 174 | TypeInfo::UInt16 => VariableData::UInt16(i as u16), 175 | TypeInfo::UInt32 => VariableData::UInt32(i as u32), 176 | TypeInfo::UInt64 => VariableData::UInt64(i as u64), 177 | TypeInfo::Pointer(_) => VariableData::UInt64(i as u64), 178 | _ => panic!("VariableData::from_i64: {:?}", typeinfo), 179 | } 180 | } 181 | pub fn from_u64(i: u64, typeinfo: &TypeInfo) -> VariableData { 182 | match typeinfo { 183 | TypeInfo::Int8 => VariableData::Int8(i as i8), 184 | TypeInfo::Int16 => VariableData::Int16(i as i16), 185 | TypeInfo::Int32 => VariableData::Int32(i as i32), 186 | TypeInfo::Int64 => VariableData::Int64(i as i64), 187 | TypeInfo::UInt8 => VariableData::UInt8(i as u8), 188 | TypeInfo::UInt16 => VariableData::UInt16(i as u16), 189 | TypeInfo::UInt32 => VariableData::UInt32(i as u32), 190 | TypeInfo::UInt64 => VariableData::UInt64(i), 191 | TypeInfo::Pointer(_) => VariableData::UInt64(i as u64), 192 | _ => panic!("VariableData::from_u64: {:?}", typeinfo), 193 | } 194 | } 195 | pub fn from_f64(f: f64, typeinfo: &TypeInfo) -> VariableData { 196 | match typeinfo { 197 | TypeInfo::Float32 => VariableData::Float32(f as f32), 198 | TypeInfo::Float64 => VariableData::Float64(f), 199 | _ => panic!("VariableData::from_f64: {:?}", typeinfo), 200 | } 201 | } 202 | pub fn to_i64(&self) -> i64 { 203 | match self { 204 | VariableData::Int8(i) => *i as i64, 205 | VariableData::Int16(i) => *i as i64, 206 | VariableData::Int32(i) => *i as i64, 207 | VariableData::Int64(i) => *i, 208 | VariableData::UInt8(i) => *i as i64, 209 | VariableData::UInt16(i) => *i as i64, 210 | VariableData::UInt32(i) => *i as i64, 211 | VariableData::UInt64(i) => *i as i64, 212 | _ => panic!("VariableData::to_i64: {:?}", self), 213 | } 214 | } 215 | pub fn to_u64(&self) -> u64 { 216 | match self { 217 | VariableData::Int8(i) => *i as u64, 218 | VariableData::Int16(i) => *i as u64, 219 | VariableData::Int32(i) => *i as u64, 220 | VariableData::Int64(i) => *i as u64, 221 | VariableData::UInt8(i) => *i as u64, 222 | VariableData::UInt16(i) => *i as u64, 223 | VariableData::UInt32(i) => *i as u64, 224 | VariableData::UInt64(i) => *i, 225 | _ => panic!("VariableData::to_u64: {:?}", self), 226 | } 227 | } 228 | pub fn to_f64(&self) -> f64 { 229 | match self { 230 | VariableData::Int8(i) => *i as f64, 231 | VariableData::Int16(i) => *i as f64, 232 | VariableData::Int32(i) => *i as f64, 233 | VariableData::Int64(i) => *i as f64, 234 | VariableData::UInt8(i) => *i as f64, 235 | VariableData::UInt16(i) => *i as f64, 236 | VariableData::UInt32(i) => *i as f64, 237 | VariableData::UInt64(i) => *i as f64, 238 | VariableData::Float32(f) => *f as f64, 239 | VariableData::Float64(f) => *f, 240 | } 241 | } 242 | 243 | pub fn is_signed_integer(&self) -> bool { 244 | match self { 245 | VariableData::Int8(_) => true, 246 | VariableData::Int16(_) => true, 247 | VariableData::Int32(_) => true, 248 | VariableData::Int64(_) => true, 249 | _ => false, 250 | } 251 | } 252 | pub fn is_unsigned_integer(&self) -> bool { 253 | match self { 254 | VariableData::UInt8(_) => true, 255 | VariableData::UInt16(_) => true, 256 | VariableData::UInt32(_) => true, 257 | VariableData::UInt64(_) => true, 258 | _ => false, 259 | } 260 | } 261 | pub fn is_float(&self) -> bool { 262 | match self { 263 | VariableData::Float32(_) => true, 264 | VariableData::Float64(_) => true, 265 | _ => false, 266 | } 267 | } 268 | } 269 | -------------------------------------------------------------------------------- /tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ehwan/C-language-Parser-In-Rust/8dfd827b67fa182840357044a79693945f90755e/tree.png --------------------------------------------------------------------------------