├── .gitattributes ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── src ├── gen.v ├── parser.v ├── token.v └── type.v ├── test.vsh └── vcc.v /.gitattributes: -------------------------------------------------------------------------------- 1 | *.vsh linguist-language=V 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | 54 | *.c 55 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 れもん 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 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | vcc: 2 | v -g -o vcc ./src 3 | 4 | test: vcc 5 | v run test.vsh 6 | make clean 7 | 8 | clean: 9 | rm -f vcc tmp* 10 | 11 | .PHONY: test clean 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VCC - The C Compiler in V 2 | 3 | This is a toy C compiler written in V. 4 | This compiler is based on [chibicc](https://github.com/rui314/chibicc) by Rui Ueyama. 5 | This is the first compiler I have made. 6 | 7 | The main object of this compiler is to compile The V Programming Language and compile itself by produced V binary. 8 | 9 | Document by Rui Ueyama(Japanese): https://sigbus.info/compilerbook 10 | My blog(Japanese): https://blog.anzu.tech/post/vcc 11 | 12 | ## Usage 13 | Please make sure that the V compiler is installed on your terminal. 14 | The V Programming Language: https://vlang.io 15 | 16 | To build VCC, run the following command 17 | ```sh 18 | v -o vcc ./src 19 | ``` 20 | or just type 21 | ```sh 22 | make 23 | ``` 24 | 25 | To compile C source code, 26 | ```sh 27 | ./vcc foobar.c > foobar.s 28 | gcc -o foobar foobar.s 29 | ``` 30 | 31 | ## Key Features of VCC 32 | - All the operators in C are implemented 33 | - `extern` and global variables/prototype declaration supported 34 | - You can declare variables in `for` statements! Yay! 35 | - Structs and Unions are supported 36 | 37 | ## and WIPs, you know 38 | - Preprocessor 39 | - Initialization 40 | - Float 41 | - Enum 42 | - Compound literal, it's well used in V 43 | 44 | ## Reference 45 | Special thanks to [Rui Ueyama](https://twitter.com/rui314) 46 | -------------------------------------------------------------------------------- /src/gen.v: -------------------------------------------------------------------------------- 1 | module src 2 | 3 | const ( 4 | Reg1 = ['dil', 'sil', 'dl', 'cl', 'r8b', 'r9b'] 5 | Reg2 = ['di', 'si', 'dx', 'cx', 'r8w', 'r9w'] 6 | Reg4 = ['edi', 'esi', 'edx', 'ecx', 'r8d', 'r9d'] 7 | Regs = ['rdi', 'rsi', 'rdx', 'rcx', 'r8', 'r9'] 8 | ) 9 | 10 | pub fn (p mut Parser) gen_main() { 11 | println('.intel_syntax noprefix') 12 | println('.data') 13 | 14 | for name, gvar in p.global { 15 | if !gvar.is_extern && !gvar.is_type && gvar.typ.kind.last() != .func { 16 | size := gvar.typ.size() 17 | if !gvar.is_static { 18 | println('.global $name') 19 | } 20 | println('$name:') 21 | println(' .zero $size') 22 | } 23 | } 24 | 25 | for i, node in p.strs { 26 | offset := node.offset 27 | content := node.name 28 | println('.L.C.$offset:') 29 | println(' .string "$content"') 30 | } 31 | 32 | println('.text') 33 | 34 | for name, func in p.code { 35 | p.curfn = func 36 | offset := align(p.curfn.offset, 16) 37 | 38 | if !func.is_static { 39 | println('.global $name') 40 | } 41 | println('$name:') 42 | println(' push rbp') 43 | println(' mov rbp, rsp') 44 | println(' sub rsp, $offset') 45 | 46 | mut fnargs := func.args 47 | maxnum := if func.num > 6 {6} else {func.num} 48 | for i in 0..maxnum { 49 | reg := match fnargs.left.typ.size() { 50 | 1 {Reg1[i]} 51 | 2 {Reg2[i]} 52 | 4 {Reg4[i]} 53 | 8 {Regs[i]} 54 | else {'none'} 55 | } 56 | if reg == 'none' { 57 | parse_err('Invalid type in arg of function $name') 58 | } 59 | println(' mov [rbp-$fnargs.left.offset], $reg') 60 | fnargs = fnargs.right 61 | } 62 | for i in 6..func.num { 63 | reg := match fnargs.left.typ.size() { 64 | 1 {'al'} 65 | 2 {'ax'} 66 | 4 {'eax'} 67 | 8 {'rax'} 68 | else {'none'} 69 | } 70 | if reg == 'none' { 71 | parse_err('Invalid type in arg of function $name') 72 | } 73 | basenum := 8 * (i - 4) 74 | println(' mov rax, [rbp+$basenum]') 75 | println(' mov [rbp-$fnargs.left.offset], $reg') 76 | fnargs = fnargs.right 77 | } 78 | 79 | p.gen(func.content) 80 | 81 | println('.L.return.$name:') 82 | println(' mov rsp, rbp') 83 | println(' pop rbp') 84 | println(' ret') 85 | } 86 | } 87 | 88 | fn (p mut Parser) gen_lval(node &Node) { 89 | if !node.kind in [.lvar, .deref] { 90 | parse_err('Assignment Error: left value is invalid') 91 | } 92 | 93 | if node.kind == .deref { 94 | p.gen(node.left) 95 | return 96 | } 97 | 98 | println(' lea rax, [rbp-$node.offset]') 99 | println(' push rax') 100 | } 101 | 102 | fn (p mut Parser) gen_gval(node &Node) { 103 | if !node.kind in [.gvar, .deref] { 104 | parse_err('Assignment Error: left value is invalid') 105 | } 106 | 107 | if node.kind == .deref { 108 | p.gen(node.left) 109 | return 110 | } 111 | 112 | println(' push offset $node.name') 113 | } 114 | 115 | fn (p Parser) gen_inc(kind Nodekind, typ &Type){ 116 | println(' pop rax') 117 | if typ.kind.last() in [.ary, .func, .strc] { 118 | parse_err('Cannot inc/decrement type `${*typ}`') 119 | } 120 | cmd := if kind in [.incb, .incf] { 121 | 'add' 122 | } else { 123 | 'sub' 124 | } 125 | if kind in [.incb, .decb] { 126 | if typ.is_unsigned() { 127 | match typ.size() { 128 | 1 {println(' movzx rdx, byte ptr [rax]')} 129 | 2 {println(' movzx rdx, word ptr [rax]')} 130 | 4 {println(' mov edx, dword ptr [rax]')} 131 | 8 {println(' mov rdx, [rax]')} 132 | else {parse_err('you are loading something wrong')} 133 | } 134 | } else { 135 | match typ.size() { 136 | 1 {println(' movsx rdx, byte ptr [rax]')} 137 | 2 {println(' movsx rdx, word ptr [rax]')} 138 | 4 {println(' movsxd rdx, dword ptr [rax]')} 139 | 8 {println(' mov rdx, [rax]')} 140 | else {parse_err('you are loading something wrong')} 141 | } 142 | } 143 | println(' push rdx') 144 | } 145 | if typ.kind.last() != .ptr { 146 | match typ.size() { 147 | 1 {println(' $cmd byte ptr [rax], 1')} 148 | 2 {println(' $cmd word ptr [rax], 1')} 149 | 4 {println(' $cmd dword ptr [rax], 1')} 150 | 8 {println(' $cmd qword ptr [rax], 1')} 151 | else {parse_err('you are loading something wrong')} 152 | } 153 | } else { 154 | size := typ.reduce().size_allow_void() 155 | println(' $cmd qword ptr [rax], $size') 156 | } 157 | if kind in [.incf, .decf] { 158 | if typ.is_unsigned() { 159 | match typ.size() { 160 | 1 {println(' movzx rdx, byte ptr [rax]')} 161 | 2 {println(' movzx rdx, word ptr [rax]')} 162 | 4 {println(' mov edx, dword ptr [rax]')} 163 | 8 {println(' mov rdx, [rax]')} 164 | else {parse_err('you are loading something wrong')} 165 | } 166 | } else { 167 | match typ.size() { 168 | 1 {println(' movsx rdx, byte ptr [rax]')} 169 | 2 {println(' movsx rdx, word ptr [rax]')} 170 | 4 {println(' movsxd rdx, dword ptr [rax]')} 171 | 8 {println(' mov rdx, [rax]')} 172 | else {parse_err('you are loading something wrong')} 173 | } 174 | } 175 | println(' push rdx') 176 | } 177 | } 178 | 179 | fn (p Parser) gen_load(typ &Type){ 180 | println(' pop rax') 181 | if typ.is_unsigned() { 182 | match typ.size() { 183 | 1 {println(' movzx rax, byte ptr [rax]')} 184 | 2 {println(' movzx rax, word ptr [rax]')} 185 | 4 {println(' mov eax, dword ptr [rax]')} 186 | 8 {println(' mov rax, [rax]')} 187 | else {parse_err('you are loading something wrong')} 188 | } 189 | } else { 190 | match typ.size() { 191 | 1 {println(' movsx rax, byte ptr [rax]')} 192 | 2 {println(' movsx rax, word ptr [rax]')} 193 | 4 {println(' movsxd rax, dword ptr [rax]')} 194 | 8 {println(' mov rax, [rax]')} 195 | else {parse_err('you are loading something wrong')} 196 | } 197 | } 198 | println(' push rax') 199 | } 200 | 201 | fn (p Parser) gen_store(typ &Type){ 202 | println(' pop rdi') 203 | println(' pop rax') 204 | if typ.kind.last() == .bool { 205 | println(' cmp rdi, 0') 206 | println(' setne dil') 207 | println(' movzb rdi, dil') 208 | } 209 | match typ.size() { 210 | 1 {println(' mov [rax], dil')} 211 | 2 {println(' mov [rax], di')} 212 | 4 {println(' mov [rax], edi')} 213 | 8 {println(' mov [rax], rdi')} 214 | else {parse_err('you are saving something wrong')} 215 | } 216 | println(' push rdi') 217 | } 218 | 219 | fn (p Parser) gen_calc(kind Nodekind) { 220 | match kind { 221 | .add {println(' add rax, rdi')} 222 | .sub {println(' sub rax, rdi')} 223 | .mul {println(' imul rax, rdi')} 224 | .div { 225 | println(' cqo') 226 | println(' idiv rdi') 227 | } 228 | .mod { 229 | println(' cqo') 230 | println(' idiv rdi') 231 | println(' mov rax, rdx') 232 | } 233 | .bitand {println(' and rax, rdi')} 234 | .bitor {println(' or rax, rdi')} 235 | .bitxor {println(' xor rax, rdi')} 236 | .shl { 237 | println(' mov cl, dil') 238 | println(' shl rax, cl') 239 | } 240 | .shr { 241 | println(' mov cl, dil') 242 | println(' sar rax, cl') 243 | } 244 | else { 245 | println(' cmp rax, rdi') 246 | match kind { 247 | .eq {println(' sete al')} 248 | .ne {println(' setne al')} 249 | .gt {println(' setg al')} 250 | .ge {println(' setge al')} 251 | else {parse_err('What?')} 252 | } 253 | println(' movzb rax, al') 254 | } 255 | } 256 | } 257 | 258 | fn (p Parser) gen_calc_unsigned(kind Nodekind, size int) { 259 | match kind { 260 | .add {println(' add rax, rdi')} 261 | .sub {println(' sub rax, rdi')} 262 | .mul {println(' mul rdi')} 263 | .div { 264 | println(' mov rdx, 0') 265 | println(' div rdi') 266 | } 267 | .mod { 268 | println(' mov rdx, 0') 269 | println(' div rdi') 270 | println(' mov rax, rdx') 271 | } 272 | .bitand {println(' and rax, rdi')} 273 | .bitor {println(' or rax, rdi')} 274 | .bitxor {println(' xor rax, rdi')} 275 | .shl { 276 | println(' mov cl, dil') 277 | println(' shl rax, cl') 278 | } 279 | .shr { 280 | println(' mov cl, dil') 281 | println(' shr rax, cl') 282 | } 283 | else { 284 | println(' cmp rax, rdi') 285 | match kind { 286 | .eq {println(' sete al')} 287 | .ne {println(' setne al')} 288 | .gt {println(' seta al')} 289 | .ge {println(' setae al')} 290 | else {parse_err('What?')} 291 | } 292 | println(' movzb rax, al') 293 | } 294 | } 295 | if size == 8 {return} 296 | println(' push rax') 297 | p.gen_cast(size, true, false) 298 | println(' pop rax') 299 | } 300 | 301 | fn (p mut Parser) gen_arg(node &Node, left int) { 302 | if left > 0 { 303 | p.gen_arg(node.right, left-1) 304 | p.gen(node.left) 305 | } 306 | } 307 | 308 | fn (p Parser) gen_cast(size int, is_unsigned bool, is_bool bool) { 309 | if size == 8 {return} 310 | if is_bool { 311 | println(' cmp rax, 0') 312 | println(' setne al') 313 | println(' movzb rax, al') 314 | return 315 | } 316 | println(' pop rax') 317 | if is_unsigned { 318 | match size { 319 | 1 {println(' movzx rax, al')} 320 | 2 {println(' movzx rax, ax')} 321 | 4 {println(' lea rax, [eax]')} 322 | else {parse_err('Unexpected size')} 323 | } 324 | } else { 325 | match size { 326 | 1 {println(' movsx rax, al')} 327 | 2 {println(' movsx rax, ax')} 328 | 4 {println(' movsxd rax, eax')} 329 | else {parse_err('Unexpected size')} 330 | } 331 | } 332 | println(' push rax') 333 | } 334 | 335 | fn (p mut Parser) gen(node &Node) { 336 | match node.kind { 337 | .ret { 338 | if node.left.kind != .nothing { 339 | p.gen(node.left) 340 | typ := p.curfn.typ 341 | p.gen_cast(typ.size(), typ.is_unsigned(), typ.kind.last() == .bool) 342 | println(' pop rax') 343 | } 344 | println(' jmp .L.return.$p.curfn.name') 345 | } 346 | .addr { 347 | if node.left.kind == .lvar { 348 | p.gen_lval(node.left) 349 | } else { 350 | p.gen_gval(node.left) 351 | } 352 | } 353 | .deref { 354 | p.gen(node.left) 355 | if !node.typ.kind.last() in [.ary, .func, .strc] { 356 | p.gen_load(node.typ) 357 | } 358 | } 359 | .incb, .decb, .incf, .decf { 360 | if node.left.kind == .lvar { 361 | p.gen_lval(node.left) 362 | } else { 363 | p.gen_gval(node.left) 364 | } 365 | p.gen_inc(node.kind, node.left.typ) 366 | } 367 | .bitnot { 368 | p.gen(node.left) 369 | println(' pop rax') 370 | println(' not rax') 371 | println(' push rax') 372 | } 373 | .comma { 374 | p.gen(node.left) 375 | println(' pop rax') 376 | p.gen(node.right) 377 | } 378 | .block { 379 | for code in node.code { 380 | p.gen(code) 381 | } 382 | } 383 | .ifn { 384 | p.gen(node.cond) 385 | println(' pop rax') 386 | println(' cmp rax, 0') 387 | println(' je .L.end.$node.num') 388 | p.gen(node.left) 389 | println('.L.end.$node.num:') 390 | } 391 | .ifelse { 392 | p.gen(node.cond) 393 | println(' pop rax') 394 | println(' cmp rax, 0') 395 | println(' je .L.else.$node.num') 396 | p.gen(node.left) 397 | println(' jmp .L.end.$node.num') 398 | println('.L.else.$node.num:') 399 | p.gen(node.right) 400 | println('.L.end.$node.num:') 401 | } 402 | .forn { 403 | p.gen(node.first) 404 | println('.L.begin.$node.num:') 405 | p.gen(node.cond) 406 | println(' pop rax') 407 | println(' cmp rax, 0') 408 | println(' je .L.end.$node.num') 409 | p.genifnum << node.num 410 | p.gencontnum << node.num 411 | p.gen(node.left) 412 | p.genifnum.delete(p.genifnum.len-1) 413 | p.gencontnum.delete(p.gencontnum.len-1) 414 | println('.L.cont.$node.num:') 415 | p.gen(node.right) 416 | println(' jmp .L.begin.$node.num') 417 | println('.L.end.$node.num:') 418 | } 419 | .while { 420 | println('.L.begin.$node.num:') 421 | p.gen(node.cond) 422 | println(' pop rax') 423 | println(' cmp rax, 0') 424 | println(' je .L.end.$node.num') 425 | p.genifnum << node.num 426 | p.gencontnum << node.num 427 | p.gen(node.left) 428 | p.genifnum.delete(p.genifnum.len-1) 429 | p.gencontnum.delete(p.gencontnum.len-1) 430 | println('.L.cont.$node.num:') 431 | println(' jmp .L.begin.$node.num') 432 | println('.L.end.$node.num:') 433 | } 434 | .do { 435 | println('.L.begin.$node.num:') 436 | p.genifnum << node.num 437 | p.gencontnum << node.num 438 | p.gen(node.left) 439 | p.genifnum.delete(p.genifnum.len-1) 440 | p.gencontnum.delete(p.gencontnum.len-1) 441 | println('.L.cont.$node.num:') 442 | p.gen(node.cond) 443 | println(' pop rax') 444 | println(' cmp rax, 0') 445 | println(' je .L.end.$node.num') 446 | println(' jmp .L.begin.$node.num') 447 | println('.L.end.$node.num:') 448 | } 449 | .swich { 450 | println('.L.begin.$node.num:') 451 | mut i := 0 452 | p.gen(node.cond) 453 | for cons in node.code { 454 | p.gen(cons) 455 | println(' pop rdi') 456 | println(' pop rax') 457 | println(' cmp rax, rdi') 458 | println(' je .L.label.case.$node.num\.$i') 459 | println(' push rax') 460 | i++ 461 | } 462 | if node.name == 'hasdefault' { 463 | println(' jmp .L.label.default.$node.num') 464 | } else { 465 | println(' jmp .L.end.$node.num') 466 | } 467 | p.genifnum << node.num 468 | p.gen(node.left) 469 | p.genifnum.delete(p.genifnum.len-1) 470 | println('.L.end.$node.num:') 471 | } 472 | .brk { 473 | if p.genifnum.len == 0 { 474 | parse_err('cannot break not in loop or switch statement') 475 | } 476 | ifnum := p.genifnum.last() 477 | println(' jmp .L.end.$ifnum') 478 | } 479 | .cont { 480 | if p.gencontnum.len == 0 { 481 | parse_err('cannot continue not in loop statement') 482 | } 483 | ifnum := p.gencontnum.last() 484 | println(' jmp .L.cont.$ifnum') 485 | } 486 | .label { 487 | println('.L.label.$node.name:') 488 | p.gen(node.left) 489 | } 490 | .gozu { 491 | if !node.name in p.curfn.labels { 492 | parse_err('$node.name used in goto but not declared') 493 | } 494 | println(' jmp .L.label.$node.name') 495 | } 496 | .num { 497 | println(' push $node.num') 498 | } 499 | .string { 500 | println(' push offset .L.C.$node.offset') 501 | } 502 | .lvar { 503 | p.gen_lval(node) 504 | if !node.typ.kind.last() in [.ary, .func, .strc] { 505 | p.gen_load(node.typ) 506 | } 507 | } 508 | .gvar { 509 | p.gen_gval(node) 510 | if !node.typ.kind.last() in [.ary, .func, .strc] { 511 | p.gen_load(node.typ) 512 | } 513 | } 514 | .assign { 515 | if node.left.typ.kind.last() == .ary { 516 | parse_err('Assignment Error: array body is not assignable') 517 | } else if node.left.typ.kind.last() == .func { 518 | parse_err('Assignment Error: function is not assignable') 519 | } else if node.typ.kind.last() == .strc { 520 | /* for i in node.code { 521 | code := i.val 522 | p.gen(code) 523 | }*/ 524 | return 525 | } 526 | if node.left.kind == .lvar { 527 | p.gen_lval(node.left) 528 | } else { 529 | p.gen_gval(node.left) 530 | } 531 | p.gen(node.right) 532 | p.gen_store(node.typ) 533 | } 534 | .calcassign { 535 | if node.left.typ.kind.last() == .ary { 536 | parse_err('Assignment Error: array body is not assignable') 537 | } else if node.left.typ.kind.last() == .func { 538 | parse_err('Assignment Error: function is not assignable') 539 | } 540 | if node.left.kind == .lvar { 541 | p.gen_lval(node.left) 542 | } else { 543 | p.gen_gval(node.left) 544 | } 545 | p.gen(node.right) 546 | p.gen(node.left) 547 | println(' pop rax') 548 | println(' pop rdi') 549 | 550 | if node.left.typ.is_unsigned() { 551 | p.gen_calc_unsigned(node.secondkind, node.left.typ.size()) 552 | } else { 553 | p.gen_calc(node.secondkind) 554 | } 555 | 556 | println(' push rax') 557 | p.gen_store(node.typ) 558 | } 559 | .call { 560 | mut args := node.left 561 | name := if node.name == '' { 562 | 'rdx' 563 | } else { 564 | node.name 565 | } 566 | println(' push 1') 567 | println(' mov rax, rsp') 568 | println(' and rax, 15') 569 | ifnum := p.ifnum 570 | p.ifnum++ 571 | if node.num % 2 == 1 { 572 | println(' jnz .L.call.$ifnum') 573 | } else { 574 | println(' jz .L.call.$ifnum') 575 | } 576 | println(' push 0') 577 | println('.L.call.$ifnum:') 578 | p.gen_arg(args, node.num) 579 | if node.name == '' { 580 | p.gen(node.right) 581 | println(' pop rdx') 582 | } 583 | for i in Regs[..node.num] { 584 | println(' pop $i') 585 | } 586 | println(' mov rax, 0') 587 | println(' call $name') 588 | if node.num > 6 { 589 | overed := 8 * (node.num - 6) 590 | println(' add rsp, $overed') 591 | } 592 | println(' pop rdi') 593 | println(' cmp rdi, 0') 594 | println(' jnz .L.end.$ifnum') 595 | println(' pop rdi') 596 | println('.L.end.$ifnum:') 597 | if node.typ.kind.last() == .bool { 598 | println(' movzb rax, al') 599 | } 600 | println(' push rax') 601 | } 602 | .sizof { 603 | size := node.left.typ.size_allow_void() 604 | println(' push $size') 605 | } 606 | .cast { 607 | p.gen(node.left) 608 | p.gen_cast(node.typ.size(), node.typ.is_unsigned(), node.typ.kind.last() == .bool) 609 | } 610 | .nothing { 611 | } 612 | else { 613 | p.gen(node.left) 614 | p.gen(node.right) 615 | 616 | println(' pop rdi') 617 | println(' pop rax') 618 | 619 | if node.typ.is_unsigned() { 620 | p.gen_calc_unsigned(node.kind, node.typ.size()) 621 | } else { 622 | p.gen_calc(node.kind) 623 | } 624 | 625 | println(' push rax') 626 | } 627 | } 628 | } 629 | 630 | -------------------------------------------------------------------------------- /src/parser.v: -------------------------------------------------------------------------------- 1 | module src 2 | 3 | fn parse_err(s string) { 4 | eprintln(s) 5 | exit(1) 6 | } 7 | 8 | fn unexp_err(token Tok, s string) { 9 | eprintln('${token.line}:${token.pos}: $s') 10 | exit(1) 11 | } 12 | 13 | fn (p Parser) token_err(s string) { 14 | program := p.progstr.split_into_lines()[p.tokens[p.pos].line-1] 15 | here := [' '].repeat(p.tokens[p.pos].pos).join('') 16 | unexp_err(p.tokens[p.pos], '$s\n$program\n$here^here') 17 | } 18 | 19 | pub struct Parser { 20 | tokens []Tok 21 | progstr string 22 | mut: 23 | pos int 24 | code map[string]&Function 25 | ifnum int 26 | genifnum []int 27 | gencontnum []int 28 | curfn &Function 29 | curbl []&Node 30 | cursw []&Node 31 | global map[string]&Lvar 32 | glstrc map[string]&Struct 33 | str_offset int 34 | strs []&Node 35 | statics int 36 | } 37 | 38 | enum Nodekind { 39 | nothing 40 | assign 41 | calcassign 42 | add 43 | sub 44 | mul 45 | div 46 | mod 47 | bitand 48 | bitor 49 | bitxor 50 | bitnot 51 | shr 52 | shl 53 | eq 54 | ne 55 | gt 56 | ge 57 | num 58 | string 59 | lvar 60 | gvar 61 | ret 62 | ifn 63 | ifelse 64 | forn 65 | while 66 | do 67 | swich 68 | brk 69 | cont 70 | block 71 | label 72 | gozu 73 | call 74 | args 75 | fnargs 76 | deref 77 | addr 78 | sizof 79 | incb 80 | decb 81 | incf 82 | decf 83 | comma 84 | cast 85 | } 86 | 87 | struct Function { 88 | name string 89 | typ &Type 90 | mut: 91 | num int 92 | args &Node 93 | content &Node 94 | offset int 95 | labels []string 96 | is_static bool 97 | is_defined bool 98 | } 99 | 100 | struct Node { 101 | kind Nodekind 102 | mut: 103 | cond &Node 104 | first &Node 105 | left &Node 106 | right &Node 107 | num int 108 | offset int 109 | name string 110 | secondkind Nodekind 111 | code []&Node 112 | typ &Type 113 | locals []&Lvar 114 | structs map[string]&Struct 115 | } 116 | 117 | struct Lvar { 118 | name string 119 | typ &Type 120 | is_global bool 121 | mut: 122 | is_static bool 123 | is_extern bool 124 | is_type bool 125 | offset int 126 | } 127 | 128 | struct Struct { 129 | name string 130 | kind Structkind 131 | mut: 132 | is_defined bool 133 | content map[string]&Lvar 134 | offset int 135 | max_align int 136 | } 137 | 138 | enum Structkind { 139 | strc 140 | unn 141 | enm 142 | } 143 | 144 | struct Funcarg { 145 | mut: 146 | args []&Lvar 147 | } 148 | 149 | fn (p Parser) look_for(op string) bool { 150 | token := p.tokens[p.pos] 151 | if token.kind != .reserved || token.str != op { 152 | return false 153 | } 154 | return true 155 | } 156 | 157 | fn (p mut Parser) look_for_label() bool { 158 | is_ident, _ := p.consume_ident() 159 | if !is_ident { 160 | return false 161 | } else { 162 | is_label := p.look_for(':') 163 | p.pos-- 164 | return is_label 165 | } 166 | } 167 | 168 | fn (p mut Parser) consume(op string) bool { 169 | token := p.tokens[p.pos] 170 | if token.kind != .reserved || token.str != op { 171 | return false 172 | } 173 | p.pos++ 174 | return true 175 | } 176 | 177 | fn (p mut Parser) consume_ident() (bool, string) { 178 | token := p.tokens[p.pos] 179 | if token.kind == .ident { 180 | p.pos++ 181 | return true, token.str 182 | } 183 | return false, '' 184 | } 185 | 186 | fn (p mut Parser) consume_string() (bool, string) { 187 | token := p.tokens[p.pos] 188 | if token.kind == .string { 189 | p.pos++ 190 | return true, token.str 191 | } 192 | return false, '' 193 | } 194 | 195 | fn (p mut Parser) consume_any(ops []string) (bool, string) { 196 | token := p.tokens[p.pos] 197 | if token.kind == .reserved && token.str in ops { 198 | p.pos++ 199 | return true, token.str 200 | } 201 | return false, '' 202 | } 203 | 204 | fn (p mut Parser) expect(op string) { 205 | token := p.tokens[p.pos] 206 | if token.kind != .reserved || token.str != op { 207 | p.token_err('Expected $op but got $token.str') 208 | } 209 | p.pos++ 210 | return 211 | } 212 | 213 | fn (p mut Parser) expect_number() int { 214 | token := p.tokens[p.pos] 215 | if token.kind != .num { 216 | p.token_err('Expected number but got $token.str') 217 | } 218 | p.pos++ 219 | return token.str.int() 220 | } 221 | 222 | fn (p mut Parser) expect_ident() string { 223 | token := p.tokens[p.pos] 224 | if token.kind != .ident { 225 | p.token_err('Expected ident but got $token.str') 226 | } 227 | p.pos++ 228 | return token.str 229 | } 230 | 231 | fn (p Parser) new_node(kind Nodekind, left, right &Node) &Node { 232 | return &Node{ 233 | kind:kind 234 | left:left 235 | right:right 236 | num:0 237 | offset:0 238 | typ:0 239 | cond:0 240 | first:0 241 | } 242 | } 243 | 244 | fn (p Parser) new_node_with_cond(kind Nodekind, cond, left, right &Node, num int) &Node { 245 | return &Node{ 246 | kind:kind 247 | cond:cond 248 | left:left 249 | right:right 250 | num:num 251 | first:0 252 | typ:0 253 | } 254 | } 255 | 256 | fn (p Parser) new_node_with_all(kind Nodekind, first, cond, left, right &Node, num int) &Node { 257 | return &Node{ 258 | kind:kind 259 | cond:cond 260 | first:first 261 | left:left 262 | right:right 263 | num:num 264 | typ:0 265 | } 266 | } 267 | 268 | fn (p Parser) new_node_num(num int) &Node { 269 | return &Node{ 270 | kind:.num 271 | num:num 272 | left:0 273 | right:0 274 | typ:0 275 | cond:0 276 | first:0 277 | } 278 | } 279 | 280 | fn (p Parser) new_node_string(str string, id int) &Node { 281 | return &Node{ 282 | kind:.string 283 | offset:id 284 | name:str 285 | left:0 286 | right:0 287 | typ:0 288 | cond:0 289 | first:0 290 | } 291 | } 292 | 293 | fn (p Parser) new_node_lvar(offset int, typ &Type) &Node { 294 | return &Node{ 295 | kind:.lvar 296 | offset:offset 297 | typ:typ 298 | left:0 299 | right:0 300 | cond:0 301 | first:0 302 | } 303 | } 304 | 305 | fn (p Parser) new_node_gvar(offset int, typ &Type, name string) &Node { 306 | return &Node{ 307 | kind:.gvar 308 | offset:offset 309 | typ:typ 310 | name:name 311 | left:0 312 | right:0 313 | cond:0 314 | first:0 315 | } 316 | } 317 | 318 | fn (p Parser) new_node_call(num int, name string, args &Node) &Node { 319 | return &Node{ 320 | kind:.call 321 | left:args 322 | right:0 323 | typ:0 324 | cond:0 325 | first:0 326 | num:num 327 | name:name 328 | } 329 | } 330 | 331 | fn (p Parser) new_node_nothing() &Node { 332 | return &Node{ 333 | kind:.nothing 334 | left:0 335 | right:0 336 | typ:0 337 | cond:0 338 | first:0 339 | } 340 | } 341 | 342 | fn (p Parser) new_func(name string, typ &Type) &Function { 343 | return &Function{ 344 | name: name 345 | typ: typ 346 | args:0 347 | content:0 348 | } 349 | } 350 | 351 | fn (p Parser) new_lvar(name string, typ &Type, offset int) &Lvar { 352 | return &Lvar{ 353 | name:name 354 | typ:typ 355 | offset:offset 356 | } 357 | } 358 | 359 | fn (p Parser) new_gvar(name string, typ &Type) &Lvar { 360 | return &Lvar{ 361 | name:name 362 | typ:typ 363 | is_global:true 364 | } 365 | } 366 | 367 | fn (p Parser) find_lvar(name string) (bool, &Lvar, bool) { 368 | mut is_curbl := true 369 | for block in p.curbl.reverse() { 370 | for lvar in block.locals { 371 | if lvar.name == name { 372 | return true, lvar, is_curbl 373 | } 374 | } 375 | is_curbl = false 376 | } 377 | if name in p.global { 378 | return true, p.global[name], is_curbl 379 | } 380 | return false, &Lvar{typ:0}, false 381 | } 382 | 383 | fn (p Parser) find_struct(name string) (bool, &Struct, bool) { 384 | mut is_curbl := true 385 | for block in p.curbl.reverse() { 386 | if name in block.structs { 387 | return true, block.structs[name], is_curbl 388 | } 389 | is_curbl = false 390 | } 391 | if name in p.glstrc { 392 | return true, p.glstrc[name], is_curbl 393 | } 394 | return false, &Struct{}, false 395 | } 396 | 397 | pub fn (p mut Parser) program() { 398 | for p.tokens[p.pos].kind != .eof { 399 | p.top() 400 | } 401 | } 402 | 403 | fn (p mut Parser) top() { 404 | is_static := p.consume('static') 405 | if is_static {p.consume('inline')} 406 | is_extern := if is_static { 407 | false 408 | } else if p.consume('inline') { 409 | true 410 | } else if p.consume('extern') { 411 | !p.consume('inline') 412 | } else { 413 | false 414 | } 415 | is_typedef := if is_static || is_extern { 416 | false 417 | } else { 418 | p.consume('typedef') 419 | } 420 | is_typ, typ, mut name := p.consume_type_allow_no_ident() 421 | if !is_typ { 422 | p.token_err('Expected type') 423 | } 424 | if name == '' { 425 | p.expect(';') 426 | return 427 | } 428 | if name in p.global {//todo 429 | gvar := p.global[name] 430 | if gvar.typ.kind.last() == .func && typ.kind.last() == .func { 431 | if is_typedef || gvar.is_type { 432 | p.token_err('`$name` is already declared') 433 | } 434 | } else { 435 | p.token_err('`$name` is already declared') 436 | } 437 | } 438 | mut gvar := p.new_gvar(name, typ) 439 | gvar.is_static = is_static 440 | gvar.is_extern = is_extern 441 | gvar.is_type = is_typedef 442 | p.global[name] = gvar 443 | if p.consume('{') { 444 | if typ.kind.last() != .func { 445 | p.token_err('Expected `;` after top level declarator') 446 | } 447 | mut func := p.function(name, typ) 448 | func.is_static = is_static 449 | p.code[name] = func 450 | } else { 451 | for !p.consume(';') { 452 | p.expect(',') 453 | mut typ2 := &Type{} 454 | typ2.kind << typ.kind.first() 455 | if typ.kind.first() == .strc { 456 | typ2.strc << typ.strc.first() 457 | } 458 | typb, str := p.consume_type_body() 459 | name = str 460 | typ2.merge(typb) 461 | if name == '' { 462 | p.token_err('There must be name in the definition') 463 | } 464 | if name in p.global {//todo 465 | p.token_err('`$name` is already declared') 466 | } 467 | mut gvar2 := p.new_gvar(name, typ2) 468 | gvar2.is_static = is_static 469 | gvar2.is_extern = is_extern 470 | gvar2.is_type = is_typedef 471 | p.global[name] = gvar2 472 | } 473 | } 474 | } 475 | 476 | fn (p mut Parser) fnargs(args &Funcarg) (&Node, []&Lvar) { 477 | mut lvars := []&Lvar 478 | mut node := p.new_node_nothing() 479 | for arg in args.args { 480 | name := arg.name 481 | typ := arg.typ 482 | if name == '' { 483 | p.token_err('Parameter name omitted') 484 | } 485 | mut lvar := p.new_lvar(name, typ, 0) 486 | p.curfn.offset += typ.size() 487 | p.curfn.offset = align(p.curfn.offset, typ.size_align()) 488 | offset := p.curfn.offset 489 | lvar.offset = offset 490 | lvars << lvar 491 | } 492 | if lvars.len != 0 { 493 | for lvar in lvars.reverse() { 494 | lvar_node := p.new_node_lvar(lvar.offset, lvar.typ) 495 | node = p.new_node(.fnargs, lvar_node, node) 496 | } 497 | } 498 | return node, lvars 499 | } 500 | 501 | fn (p mut Parser) function(name string, typ &Type) &Function { 502 | /* is_struct_return := typ.size() > 16 503 | mut rettyp := typ.reduce() 504 | if is_struct_return { 505 | rettyp.kind << Typekind.ptr 506 | }*/ 507 | mut func := p.new_func(name, typ.reduce()) 508 | p.curfn = func 509 | funcarg := typ.func.last() 510 | num := funcarg.args.len 511 | args, lvars := p.fnargs(funcarg) 512 | 513 | func.args = args 514 | func.num = num 515 | mut content := p.new_node(.block, p.new_node_nothing(), p.new_node_nothing()) 516 | p.curbl << content 517 | content.locals << lvars 518 | p.block_without_curbl(mut content) 519 | p.curbl.delete(p.curbl.len-1) 520 | func.content = content 521 | p.curfn = 0 522 | return func 523 | } 524 | 525 | fn (p mut Parser) declare(typ &Type, name string, is_typedef bool) int { 526 | is_lvar, _, is_curbl := p.find_lvar(name) 527 | if is_lvar && is_curbl { 528 | p.token_err('`$name` is already declared') 529 | } 530 | if !is_typedef { 531 | p.curfn.offset += typ.size() 532 | p.curfn.offset = align(p.curfn.offset, typ.size_align()) 533 | } 534 | offset := p.curfn.offset 535 | mut nlvar := p.new_lvar(name, typ, offset) 536 | nlvar.is_type = is_typedef 537 | mut block := p.curbl.last() 538 | block.locals << nlvar 539 | return offset 540 | } 541 | 542 | fn (p mut Parser) initialize(typ &Type, offset int) { 543 | if typ.kind.last() == .ary { 544 | } else if typ.kind.last() == .strc { 545 | members := (typ.strc.last()).content 546 | mut ignored := (members.keys()).len == 0 547 | mut keys := [['']] 548 | keys.delete(0) 549 | mut first := true 550 | for !p.consume('}') { 551 | if first { 552 | first = false 553 | } else { 554 | p.expect(',') 555 | } 556 | if p.consume('.') { 557 | name := p.expect_ident() 558 | p.expect('=') 559 | if !name in members { 560 | p.token_err('There is no member called `$name`') 561 | } 562 | } 563 | member := members[keys[0][0]] 564 | if p.consume('{')/*member.typ.kind.last() in [.array, .strc]*/ { 565 | } else { 566 | node := p.assign() 567 | if !ignored { 568 | ignored=true//stab 569 | keys<<[['']]//stab 570 | } 571 | } 572 | } 573 | } else { 574 | if p.consume('{') { 575 | p.initialize(typ, offset) 576 | } else { 577 | node := p.assign() 578 | } 579 | for p.consume(',') { 580 | if p.consume('{') { 581 | p.initialize(typ, offset) 582 | } else { 583 | p.assign() 584 | } 585 | } 586 | p.expect('}') 587 | } 588 | } 589 | 590 | fn (p mut Parser) stmt() &Node { 591 | mut node := p.new_node_nothing() 592 | if p.consume('return') { 593 | if !p.consume(';') { 594 | node = p.expr() 595 | p.expect(';') 596 | } 597 | node = p.new_node(.ret, node, p.new_node_nothing()) 598 | } else if p.consume('{') { 599 | node = p.block() 600 | } else if p.consume('if') { 601 | p.expect('(') 602 | expr := p.expr() 603 | p.expect(')') 604 | stmt_true := p.stmt() 605 | if p.consume('else') { 606 | stmt_false := p.stmt() 607 | node = p.new_node_with_cond(.ifelse, expr, stmt_true, stmt_false, p.ifnum) 608 | node.name = 'stmt' 609 | } else { 610 | node = p.new_node_with_cond(.ifn, expr, stmt_true, p.new_node_nothing(), p.ifnum) 611 | } 612 | p.ifnum++ 613 | } else if p.consume('for') { 614 | p.expect('(') 615 | mut outer_block := p.new_node(.block, p.new_node_nothing(), p.new_node_nothing()) 616 | p.curbl << outer_block 617 | mut node_tmp := p.new_node_nothing() 618 | if p.consume('typedef') || p.consume('static') { 619 | p.token_err('Declaration of non-local variable in `for` loop') 620 | } 621 | is_decl, fortyp := p.consume_type_base() 622 | if is_decl { 623 | mut first := true 624 | for !p.consume(';') { 625 | mut typ := fortyp.clone() 626 | if first { 627 | first = false 628 | } else { 629 | p.expect(',') 630 | } 631 | typb, name := p.consume_type_body() 632 | typ.merge(typb) 633 | if name == '' { 634 | p.token_err('There must be name in the definition') 635 | } 636 | p.check_func_typ(typ) 637 | offset := p.declare(typ, name, false) 638 | if p.consume('='){ 639 | lvar := p.new_node_lvar(offset, typ) 640 | mut assign := p.new_node(.assign, lvar, p.assign()) 641 | assign.add_type() 642 | outer_block.code << assign 643 | } 644 | } 645 | } 646 | first := if is_decl || p.consume(';') { 647 | p.new_node_num(0) 648 | } else { 649 | node_tmp = p.expr() 650 | p.expect(';') 651 | node_tmp 652 | } 653 | cond := if p.consume(';') { 654 | p.new_node_num(1) 655 | } else { 656 | node_tmp = p.expr() 657 | p.expect(';') 658 | node_tmp 659 | } 660 | right := if p.consume(')') { 661 | p.new_node_num(0) 662 | } else { 663 | node_tmp = p.expr() 664 | p.expect(')') 665 | node_tmp 666 | } 667 | stmt := p.stmt() 668 | outer_block.code << p.new_node_with_all(.forn, first, cond, stmt, right, p.ifnum) 669 | p.curbl.delete(p.curbl.len-1) 670 | node = outer_block 671 | p.ifnum++ 672 | } else if p.consume('while') { 673 | p.expect('(') 674 | expr := p.expr() 675 | p.expect(')') 676 | stmt := p.stmt() 677 | node = p.new_node_with_cond(.while, expr, stmt, p.new_node_nothing(), p.ifnum) 678 | p.ifnum++ 679 | } else if p.consume('do') { 680 | stmt := p.stmt() 681 | p.expect('while') 682 | p.expect('(') 683 | expr := p.expr() 684 | p.expect(')') 685 | p.expect(';') 686 | node = p.new_node_with_cond(.do, expr, stmt, p.new_node_nothing(), p.ifnum) 687 | p.ifnum++ 688 | } else if p.consume('switch') { 689 | p.expect('(') 690 | expr := p.expr() 691 | p.expect(')') 692 | node = p.new_node_with_cond(.swich, expr, p.new_node_nothing(), p.new_node_nothing(), p.ifnum) 693 | p.ifnum++ 694 | p.cursw << node 695 | mut block := p.new_node(.block, p.new_node_nothing(), p.new_node_nothing()) 696 | block.secondkind = .swich 697 | p.curbl << block 698 | p.expect('{') 699 | p.block_without_curbl(mut block) 700 | p.curbl.delete(p.curbl.len-1) 701 | p.cursw.delete(p.cursw.len-1) 702 | node.left = block 703 | } else if p.consume('break') { 704 | node = p.new_node(.brk, p.new_node_nothing(), p.new_node_nothing()) 705 | p.expect(';') 706 | } else if p.consume('continue') { 707 | node = p.new_node(.cont, p.new_node_nothing(), p.new_node_nothing()) 708 | p.expect(';') 709 | } else if p.consume('goto') { 710 | node = p.new_node(.gozu, p.new_node_nothing(), p.new_node_nothing()) 711 | node.name = p.expect_ident() 712 | p.expect(';') 713 | } else if p.consume('case') { 714 | if (p.curbl.last()).secondkind != .swich { 715 | p.token_err('`case` should be in switch block') 716 | } 717 | mut swblock := p.cursw.last() 718 | value := p.ternary() 719 | p.expect(':') 720 | num := swblock.num 721 | id := swblock.offset 722 | swblock.offset++ 723 | swblock.code << value 724 | node = p.new_node(.label, p.stmt(), p.new_node_nothing()) 725 | node.name = 'case.$num\.$id' 726 | } else if p.consume('default') { 727 | if (p.curbl.last()).secondkind != .swich { 728 | p.token_err('`case` should be in switch block') 729 | } 730 | mut swblock := p.cursw.last() 731 | p.expect(':') 732 | num := swblock.num 733 | swblock.name = 'hasdefault' 734 | node = p.new_node(.label, p.stmt(), p.new_node_nothing()) 735 | node.name = 'default.$num' 736 | } else if p.consume(';') { 737 | node = p.new_node(.nothing, p.new_node_nothing(), p.new_node_nothing()) 738 | } else if p.look_for_label() { 739 | name := p.expect_ident() 740 | if name in p.curfn.labels { 741 | p.token_err('Label `$name` is already declared') 742 | } 743 | p.curfn.labels << name 744 | p.expect(':') 745 | node = p.new_node(.label, p.stmt(), p.new_node_nothing()) 746 | node.name = name 747 | } else { 748 | node = p.expr() 749 | p.expect(';') 750 | } 751 | node.add_type() 752 | return node 753 | } 754 | 755 | fn (p mut Parser) block() &Node { 756 | mut node := p.new_node(.block, p.new_node_nothing(), p.new_node_nothing()) 757 | p.curbl << node 758 | 759 | p.block_without_curbl(mut node) 760 | 761 | p.curbl.delete(p.curbl.len-1) 762 | return node 763 | } 764 | 765 | fn (p mut Parser) block_without_curbl(node mut Node) { 766 | for !p.consume('}') { 767 | is_static := p.consume('static') 768 | is_typedef := if is_static { 769 | false 770 | } else { 771 | p.consume('typedef') 772 | } 773 | is_dec, typ_base := p.consume_type_base() 774 | if is_dec { 775 | mut first := true 776 | for !p.consume(';') { 777 | mut typ := typ_base.clone() 778 | if first { 779 | first = false 780 | } else { 781 | p.expect(',') 782 | } 783 | typb, name := p.consume_type_body() 784 | typ.merge(typb) 785 | p.check_func_typ(typ) 786 | if is_static { 787 | is_lvar, _, is_curbl := p.find_lvar(name) 788 | if is_lvar && is_curbl { 789 | p.token_err('`$name` is already declared') 790 | } 791 | p.statics++ 792 | offset := p.statics 793 | mut lvar := p.new_lvar(name, typ, offset) 794 | lvar.is_static = true 795 | p.global['$name\.$offset'] = lvar 796 | mut block := p.curbl.last() 797 | block.locals << lvar 798 | } else if typ.kind.last() == .func { 799 | is_lvar, _, is_curbl := p.find_lvar(name) 800 | if is_lvar && is_curbl { 801 | p.token_err('`$name` is already declared') 802 | } 803 | mut lvar := p.new_lvar(name, typ, 0) 804 | mut block := p.curbl.last() 805 | block.locals << lvar 806 | } else { 807 | offset := p.declare(typ, name, is_typedef) 808 | if !is_typedef && p.consume('=') { 809 | lvar := p.new_node_lvar(offset, typ) 810 | mut assign := p.new_node(.assign, lvar, p.assign()) 811 | assign.add_type() 812 | node.code << assign 813 | } 814 | } 815 | } 816 | } else { 817 | if is_static || is_typedef { 818 | p.token_err('Expected type') 819 | } 820 | node.code << p.stmt() 821 | } 822 | } 823 | } 824 | 825 | fn (p mut Parser) expr() &Node { 826 | mut node := p.assign() 827 | for { 828 | if p.consume(',') { 829 | node = p.new_node(.comma, node, p.assign()) 830 | } else { 831 | return node 832 | } 833 | } 834 | return node 835 | } 836 | 837 | fn (p mut Parser) assign() &Node { 838 | mut node := p.ternary() 839 | 840 | if p.consume('=') { 841 | node = p.new_node(.assign, node, p.assign()) 842 | node.add_type() 843 | if node.typ.kind.last() == .strc { 844 | if node.right.typ.kind.last() != .strc { 845 | p.token_err('Incompatible type `$node.right.typ.str()` when assigning to `$node.typ.str()`') 846 | } else if node.typ.strc.last() != node.right.typ.strc.last() { 847 | p.token_err('Incompatible struct/union when assigning `$node.right.typ.str()` to `$node.typ.str()`') 848 | } 849 | typ := node.typ.clone() 850 | node = p.new_node(.args, node.left, p.new_node(.args, node.right, p.new_node(.args, p.new_node_num(node.typ.size()), p.new_node_nothing()))) 851 | node.add_type() 852 | node = p.new_node_call(3, 'memcpy', node) 853 | node.typ = typ 854 | } 855 | } else { 856 | is_assign, op := p.consume_any(['+=', '-=', '*=', '/=', '%=', '&=', '|=', '^=', '<<=', '>>=']) 857 | if is_assign { 858 | node.add_type() 859 | mut calcee := p.assign() 860 | if node.typ.kind.last() == .ptr { 861 | body := node.typ.reduce() 862 | calcee = p.new_node(.mul, calcee, p.new_node_num(body.size_allow_void())) 863 | } 864 | node = p.new_node(.calcassign, node, calcee) 865 | node.secondkind = match op { 866 | '+=' {Nodekind.add} 867 | '-=' {Nodekind.sub} 868 | '*=' {Nodekind.mul} 869 | '/=' {Nodekind.div} 870 | '%=' {Nodekind.mod} 871 | '&=' {Nodekind.bitand} 872 | '|=' {Nodekind.bitor} 873 | '^=' {Nodekind.bitxor} 874 | '<<=' {Nodekind.shl} 875 | '>>=' {Nodekind.shr} 876 | else {.nothing} 877 | } 878 | } 879 | } 880 | return node 881 | } 882 | 883 | fn (p mut Parser) ternary() &Node { 884 | mut node := p.logor() 885 | if p.consume('?') { 886 | expr_true := p.expr() 887 | p.expect(':') 888 | node = p.new_node_with_cond(.ifelse, node, expr_true, p.ternary(), p.ifnum) 889 | p.ifnum++ 890 | } 891 | return node 892 | } 893 | 894 | fn (p mut Parser) logor() &Node { 895 | mut node := p.logand() 896 | 897 | for { 898 | if p.consume('||') { 899 | node = p.new_node_with_cond(.ifelse, node, p.new_node_num(1), p.new_node(.ne, p.logand(), p.new_node_num(0)), p.ifnum) 900 | p.ifnum++ 901 | } else { 902 | return node 903 | } 904 | } 905 | return node 906 | } 907 | 908 | fn (p mut Parser) logand() &Node { 909 | mut node := p.bitor() 910 | 911 | for { 912 | if p.consume('&&') { 913 | node = p.new_node_with_cond(.ifelse, node, p.new_node(.ne, p.bitor(), p.new_node_num(0)), p.new_node_num(0), p.ifnum) 914 | p.ifnum++ 915 | } else { 916 | return node 917 | } 918 | } 919 | return node 920 | } 921 | 922 | fn (p mut Parser) bitor() &Node { 923 | mut node := p.bitxor() 924 | 925 | for { 926 | if p.consume('|') { 927 | node = p.new_node(.bitor, node, p.bitxor()) 928 | } else { 929 | return node 930 | } 931 | } 932 | return node 933 | } 934 | 935 | fn (p mut Parser) bitxor() &Node { 936 | mut node := p.bitand() 937 | 938 | for { 939 | if p.consume('^') { 940 | node = p.new_node(.bitxor, node, p.bitand()) 941 | } else { 942 | return node 943 | } 944 | } 945 | return node 946 | } 947 | 948 | fn (p mut Parser) bitand() &Node { 949 | mut node := p.equality() 950 | 951 | for { 952 | if p.consume('&') { 953 | node = p.new_node(.bitand, node, p.equality()) 954 | } else { 955 | return node 956 | } 957 | } 958 | return node 959 | } 960 | 961 | fn (p mut Parser) equality() &Node { 962 | mut node := p.relational() 963 | 964 | for { 965 | if p.consume('==') { 966 | node = p.new_node(.eq, node, p.relational()) 967 | } else if p.consume('!=') { 968 | node = p.new_node(.ne, node, p.relational()) 969 | } else { 970 | return node 971 | } 972 | } 973 | return node 974 | } 975 | 976 | fn (p mut Parser) relational() &Node { 977 | mut node := p.shift() 978 | 979 | for { 980 | if p.consume('>') { 981 | node = p.new_node(.gt, node, p.add()) 982 | } else if p.consume('>=') { 983 | node = p.new_node(.ge, node, p.add()) 984 | } else if p.consume('<') { 985 | node = p.new_node(.gt, p.add(), node) 986 | } else if p.consume('<=') { 987 | node = p.new_node(.ge, p.add(), node) 988 | } else { 989 | return node 990 | } 991 | } 992 | return node 993 | } 994 | 995 | fn (p mut Parser) shift() &Node { 996 | mut node := p.add() 997 | 998 | for { 999 | if p.consume('<<') { 1000 | node = p.new_node(.shl, node, p.add()) 1001 | } else if p.consume('>>') { 1002 | node = p.new_node(.shr, node, p.add()) 1003 | } else { 1004 | return node 1005 | } 1006 | } 1007 | return node 1008 | } 1009 | 1010 | fn (p mut Parser) add() &Node { 1011 | mut node := p.mul() 1012 | 1013 | for { 1014 | if p.consume('+') { 1015 | plus_token := p.tokens[p.pos] 1016 | mut right := p.mul() 1017 | node.add_type() 1018 | right.add_type() 1019 | mut typ := &Type{} 1020 | if node.typ.is_ptr() && right.typ.is_int() { 1021 | typ = node.typ.reduce() 1022 | num := p.new_node_num(typ.size_allow_void()) 1023 | typ = node.typ.cast_ary() 1024 | right = p.new_node(.mul, right, num) 1025 | right.typ = typ.clone() 1026 | } else if node.typ.is_int() && right.typ.is_ptr() { 1027 | typ = right.typ.reduce() 1028 | num := p.new_node_num(typ.size_allow_void()) 1029 | typ = right.typ.cast_ary() 1030 | node = p.new_node(.mul, node, num) 1031 | node.typ = typ.clone() 1032 | } else if node.typ.is_int() && right.typ.is_int() { 1033 | typ = type_max(node.typ, right.typ).clone() 1034 | } else { 1035 | unexp_err(plus_token, 'Operator + cannot add two pointers') 1036 | } 1037 | node = p.new_node(.add, node, right) 1038 | node.typ = typ 1039 | } else if p.consume('-') { 1040 | minus_token := p.tokens[p.pos] 1041 | mut right := p.mul() 1042 | node.add_type() 1043 | right.add_type() 1044 | mut typ := &Type{} 1045 | if node.typ.is_ptr() && right.typ.is_int() { 1046 | typ = node.typ.reduce() 1047 | num := p.new_node_num(typ.size_allow_void()) 1048 | typ = node.typ.cast_ary() 1049 | right = p.new_node(.mul, right, num) 1050 | } else if node.typ.is_ptr() && right.typ.is_ptr() { 1051 | typ = node.typ.reduce() 1052 | num := p.new_node_num(typ.size_allow_void()) 1053 | typ.kind = [Typekind.long] 1054 | typ.suffix = [] 1055 | node = p.new_node(.div, node, num) 1056 | right = p.new_node(.div, right, num) 1057 | } else if node.typ.is_int() && right.typ.is_int() { 1058 | typ = type_max(node.typ, right.typ).clone() 1059 | } else { 1060 | unexp_err(minus_token, 'Operator - cannot subtract pointers from int') 1061 | } 1062 | node = p.new_node(.sub, node, right) 1063 | node.typ = typ 1064 | } else { 1065 | return node 1066 | } 1067 | } 1068 | return node 1069 | } 1070 | 1071 | fn (p mut Parser) mul() &Node { 1072 | mut node := p.cast() 1073 | 1074 | for { 1075 | if p.consume('*') { 1076 | node = p.new_node(.mul, node, p.cast()) 1077 | } else if p.consume('/') { 1078 | node = p.new_node(.div, node, p.cast()) 1079 | } else if p.consume('%') { 1080 | node = p.new_node(.mod, node, p.cast()) 1081 | } else { 1082 | return node 1083 | } 1084 | } 1085 | return node 1086 | } 1087 | 1088 | fn (p mut Parser) cast() &Node { 1089 | if p.look_for_bracket_with_type() { 1090 | p.expect('(') 1091 | _, typ := p.consume_type_nostring() 1092 | if typ.kind.last() in [.ary, .func, .strc] { 1093 | p.token_err('Cannot cast to `${*typ}`') 1094 | } 1095 | p.expect(')') 1096 | mut node := p.cast() 1097 | node.add_type() 1098 | node.typ = node.typ.cast_ary() 1099 | node = p.new_node(.cast, node, p.new_node_nothing()) 1100 | node.typ = typ 1101 | return node 1102 | } 1103 | return p.unary() 1104 | } 1105 | 1106 | fn (p mut Parser) unary() &Node { 1107 | if p.consume('sizeof') { 1108 | if p.look_for_bracket_with_type() { 1109 | p.expect('(') 1110 | is_typ, typ := p.consume_type_nostring() 1111 | if !is_typ { 1112 | p.token_err('Expected type') 1113 | } 1114 | p.expect(')') 1115 | mut node := p.new_node_num(0) 1116 | node.typ = typ 1117 | return p.new_node(.sizof, node, p.new_node_nothing()) 1118 | } 1119 | return p.new_node(.sizof, p.unary(), p.new_node_nothing()) 1120 | } else if p.consume('*') { 1121 | return p.new_node(.deref, p.unary(), p.new_node_nothing()) 1122 | } else if p.consume('&') { 1123 | return p.new_node(.addr, p.unary(), p.new_node_nothing()) 1124 | } else if p.consume('++') { 1125 | return p.new_node(.incf, p.unary(), p.new_node_nothing()) 1126 | } else if p.consume('--') { 1127 | return p.new_node(.decf, p.unary(), p.new_node_nothing()) 1128 | } else if p.consume('+') { 1129 | return p.unary() 1130 | } else if p.consume('-') { 1131 | return p.new_node(.sub, p.new_node_num(0), p.unary()) 1132 | } else if p.consume('~') { 1133 | return p.new_node(.bitnot, p.unary(), p.new_node_nothing()) 1134 | } else if p.consume('!') { 1135 | return p.new_node(.eq, p.unary(), p.new_node_num(0)) 1136 | } 1137 | return p.postfix() 1138 | } 1139 | 1140 | fn (p mut Parser) postfix() &Node { 1141 | mut node := p.primary() 1142 | 1143 | for { 1144 | if p.consume('++') { 1145 | node = p.new_node(.incb, node, p.new_node_nothing()) 1146 | } else if p.consume('--') { 1147 | node = p.new_node(.decb, node, p.new_node_nothing()) 1148 | } else if p.consume('[') { 1149 | mut right := p.expr() 1150 | node.add_type() 1151 | right.add_type() 1152 | mut typ := &Type{} 1153 | if node.typ.is_ptr() && right.typ.is_int() { 1154 | typ = node.typ.reduce() 1155 | num := p.new_node_num(typ.size_allow_void()) 1156 | typ.kind = node.typ.kind.clone() 1157 | typ.suffix = node.typ.suffix.clone() 1158 | right = p.new_node(.mul, right, num) 1159 | right.typ = typ.clone() 1160 | } else if node.typ.is_int() && right.typ.is_ptr() { 1161 | typ = right.typ.reduce() 1162 | num := p.new_node_num(typ.size_allow_void()) 1163 | typ.kind = node.typ.kind.clone() 1164 | typ.suffix = node.typ.suffix.clone() 1165 | node = p.new_node(.mul, node, num) 1166 | node.typ = typ.clone() 1167 | } else if node.typ.is_int() && right.typ.is_int() { 1168 | p.token_err('Either expression in a[b] should be pointer') 1169 | } else { 1170 | p.token_err('Both body and suffix are pointers in a[b] expression') 1171 | } 1172 | node = p.new_node(.add, node, right) 1173 | node.typ = typ 1174 | node = p.new_node(.deref, node, p.new_node_nothing()) 1175 | p.expect(']') 1176 | } else if p.consume('(') { 1177 | name := if node.kind == .gvar && node.typ.kind.last() == .func { 1178 | node.name 1179 | } else { 1180 | '' 1181 | } 1182 | node.add_type() 1183 | if node.typ.kind.last() != .func { 1184 | if !node.typ.is_ptr() { 1185 | p.token_err('Cannot call non-functional type') 1186 | } else { 1187 | mut typ := node.typ 1188 | for typ.is_ptr() { 1189 | typ = typ.reduce() 1190 | } 1191 | if typ.kind.last() != .func { 1192 | p.token_err('Cannot call non-functional type') 1193 | } 1194 | } 1195 | } 1196 | func := node 1197 | if p.consume(')') { 1198 | node = p.new_node_call(0, name, p.new_node_nothing()) 1199 | node.right = func 1200 | } else { 1201 | args, num := p.args() 1202 | p.expect(')') 1203 | node = p.new_node_call(num, name, args) 1204 | node.right = func 1205 | } 1206 | node.add_type() 1207 | node.typ = func.typ 1208 | for node.typ.is_ptr() { 1209 | node.typ = node.typ.reduce() 1210 | } 1211 | node.typ = node.typ.reduce() 1212 | } else if p.consume('.') { 1213 | node.add_type() 1214 | if node.typ.kind.last() != .strc { 1215 | p.token_err('Expected struct/union type') 1216 | } 1217 | strc := node.typ.strc.last() 1218 | name := p.expect_ident() 1219 | if !name in strc.content { 1220 | p.token_err('There is no member named `$name`') 1221 | } 1222 | member := strc.content[name] 1223 | node = p.new_node(.add, node, p.new_node_num(member.offset)) 1224 | node.typ = member.typ.clone() 1225 | node.typ.kind << Typekind.ptr 1226 | node = p.new_node(.deref, node, p.new_node_nothing()) 1227 | } else if p.consume('->') { 1228 | node.add_type() 1229 | if !node.typ.is_ptr() || (node.typ.reduce()).kind.last() != .strc { 1230 | p.token_err('Expected pointer/array of struct/union type') 1231 | } 1232 | strc := node.typ.strc.last() 1233 | name := p.expect_ident() 1234 | if !name in strc.content { 1235 | p.token_err('There is no member named `$name`') 1236 | } 1237 | member := strc.content[name] 1238 | node = p.new_node(.add, node, p.new_node_num(member.offset)) 1239 | node.typ = member.typ.clone() 1240 | node.typ.kind << Typekind.ptr 1241 | node = p.new_node(.deref, node, p.new_node_nothing()) 1242 | } else { 1243 | return node 1244 | } 1245 | } 1246 | return node 1247 | } 1248 | 1249 | fn (p mut Parser) args() (&Node, int) { 1250 | expr := p.assign() 1251 | if p.consume(',') { 1252 | args, num := p.args() 1253 | return p.new_node(.args, expr, args), num+1 1254 | } 1255 | return p.new_node(.args, expr, p.new_node_nothing()), 1 1256 | } 1257 | 1258 | fn (p mut Parser) primary() &Node { 1259 | if p.consume('(') { 1260 | node := p.expr() 1261 | p.expect(')') 1262 | return node 1263 | } 1264 | is_ident, name := p.consume_ident() 1265 | if !is_ident { 1266 | is_string, content := p.consume_string() 1267 | if is_string { 1268 | node := p.new_node_string(content, p.str_offset) 1269 | p.str_offset++ 1270 | p.strs << node 1271 | return node 1272 | } 1273 | return p.new_node_num(p.expect_number()) 1274 | } 1275 | 1276 | is_lvar, lvar, _ := p.find_lvar(name) 1277 | if !is_lvar { 1278 | p.token_err('`$name` is not declared yet') 1279 | } else if lvar.is_type { 1280 | p.token_err('`$name` is declared as type') 1281 | } 1282 | node := if lvar.is_global || lvar.typ.kind.last() == .func { 1283 | p.new_node_gvar(lvar.offset, lvar.typ, name) 1284 | } else if lvar.is_static { 1285 | p.new_node_gvar(lvar.offset, lvar.typ, '$name\.$lvar.offset') 1286 | } else { 1287 | p.new_node_lvar(lvar.offset, lvar.typ) 1288 | } 1289 | return node 1290 | } 1291 | 1292 | -------------------------------------------------------------------------------- /src/token.v: -------------------------------------------------------------------------------- 1 | module src 2 | 3 | struct Tok { 4 | kind Token 5 | str string 6 | line int 7 | pos int 8 | } 9 | 10 | enum Token { 11 | eof 12 | ident 13 | reserved 14 | num 15 | string 16 | } 17 | 18 | fn new_token(token Token, s string, line, pos int) Tok { 19 | return Tok{token, s, line, pos} 20 | } 21 | 22 | fn is_token_string(p, needle string, pos int) bool { 23 | len := needle.len 24 | if pos + len <= p.len && p[pos..pos+len] == needle && 25 | !p[pos + len].is_letter() && !p[pos + len].is_digit() && p[pos + len] != `_` { 26 | return true 27 | } else { 28 | return false 29 | } 30 | } 31 | 32 | fn hex_to_num(b byte) int { 33 | if b >= `0` && b <= `9` { 34 | return int(b - `0`) 35 | } 36 | if b >= `A` && b <= `F` { 37 | return int(b - `A` + 10) 38 | } 39 | return int(b - `a` + 10) 40 | } 41 | 42 | pub fn tokenize(p string) []Tok { 43 | mut tokens := []Tok 44 | mut pos := 0 45 | mut line := 1 46 | mut lpos := 0 47 | 48 | for pos < p.len { 49 | if p[pos] == `\n` { 50 | pos++ 51 | line++ 52 | lpos = 0 53 | continue 54 | } 55 | 56 | if p[pos].is_space() { 57 | pos++ 58 | lpos++ 59 | continue 60 | } 61 | 62 | if pos + 2 <= p.len && p[pos..pos+2] == '//' { 63 | pos++ 64 | lpos++ 65 | for pos < p.len && !(p[pos-1] != `\\` && p[pos] == `\n`) { 66 | pos++ 67 | lpos++ 68 | } 69 | continue 70 | } 71 | 72 | if p[pos] == `#` { //this is a hack for preprocessed gcc code 73 | pos++ 74 | lpos++ 75 | for pos < p.len && !(p[pos-1] != `\\` && p[pos] == `\n`) { 76 | pos++ 77 | lpos++ 78 | } 79 | continue 80 | } 81 | 82 | if pos + 2 <= p.len && p[pos..pos+2] == '/*' { 83 | pos += 3 84 | lpos += 3 85 | for pos < p.len && !(p[pos-1] == `*` && p[pos] == `/`) { 86 | pos++ 87 | lpos++ 88 | if p[pos] == `\n` { 89 | line++ 90 | lpos = 0 91 | } 92 | } 93 | pos++ 94 | line++ 95 | continue 96 | } 97 | 98 | if pos + 2 <= p.len && p[pos..pos+2] == '\\\n' { 99 | pos += 2 100 | lpos = 0 101 | line++ 102 | } 103 | 104 | reserves := [ 105 | '_Bool', '_Complex', '_Imaginary', 106 | 'auto', 'break', 'case', 'char', 'const', 'continue', 'default', 'do', 107 | 'double', 'else', 'enum', 'extern', 'float', 'for', 'goto', 'if', 108 | 'inline', 'int', 'long', 'register', 'restrict', 'return', 'signed', 109 | 'sizeof', 'short', 'static', 'struct', 'switch', 'typedef', 'union', 110 | 'unsigned', 'void', 'volatile', 'while' 111 | ] 112 | 113 | for res in reserves { 114 | if is_token_string(p, res, pos) { 115 | tokens << new_token(.reserved, res, line, lpos) 116 | pos += res.len 117 | lpos += res.len 118 | goto cont 119 | } 120 | } 121 | 122 | if pos + 2 < p.len && (p[pos..pos+3] in ['<<=', '>>=', '...']) { 123 | tokens << new_token(.reserved, p[pos..pos+3], line, lpos) 124 | pos += 3 125 | lpos += 3 126 | continue 127 | } 128 | 129 | if pos + 1 < p.len && (p[pos..pos+2] in ['==', '!=', '>=', '<=', '&&', '||', '++', '--', '->', '<<', '>>', '+=', '-=', '*=', '/=', '%=', '&=', '|=', '^=']) { 130 | tokens << new_token(.reserved, p[pos..pos+2], line, lpos) 131 | pos += 2 132 | lpos += 2 133 | continue 134 | } 135 | 136 | if p[pos] in [`+`, `-`, `*`, `/`, `(`, `)`, `<`, `>`, `;`, `=`, `{`, `}`, `,`, `&`, `[`, `]`, `%`, `!`, `|`, `^`, `~`, `?`, `:`, `.`] { 137 | tokens << new_token(.reserved, p[pos].str(), line, lpos) 138 | pos++ 139 | lpos++ 140 | continue 141 | } 142 | 143 | if p[pos] == `"` { 144 | pos++ 145 | lpos++ 146 | start_pos := pos 147 | for p[pos] != `"` { 148 | if p[pos] == `\\` { 149 | pos++ 150 | lpos++ 151 | if p[pos] == `\n` { 152 | line++ 153 | lpos = 0 154 | } 155 | } 156 | pos++ 157 | lpos++ 158 | if p[pos] == `\n` { 159 | line++ 160 | lpos = 0 161 | } 162 | } 163 | if tokens.len > 0 && tokens[tokens.len-1].kind == .string { 164 | tokens[tokens.len-1] = new_token(.string, tokens[tokens.len-1].str + p[start_pos..pos].replace('\\\n', ''), line, lpos) 165 | } else { 166 | tokens << new_token(.string, p[start_pos..pos].replace('\\\n', ''), line, lpos) 167 | } 168 | pos++ 169 | lpos++ 170 | continue 171 | } 172 | 173 | if p[pos] == `'` { 174 | pos+=2 175 | lpos+=2 176 | mut num := 0 177 | if p[pos-1] == `\\` { 178 | num = match p[pos] { 179 | `0` {0} 180 | `a` {7} 181 | `b` {8} 182 | `f` {12} 183 | `n` {10} 184 | `r` {13} 185 | `t` {9} 186 | `v` {11} 187 | `x` {256} 188 | `0`, `1`, `2`, `3`, `4`, `5`, `6`, `7` {257} 189 | else {int(p[pos])} 190 | } 191 | match num { 192 | 256 { 193 | pos++ 194 | lpos++ 195 | if !p[pos].is_hex_digit() {parse_err('$line:$lpos: Expected hex digit')} 196 | num = hex_to_num(p[pos]) 197 | if p[pos+1] != `'` { 198 | pos++ 199 | lpos++ 200 | if !p[pos].is_hex_digit() {parse_err('$line:$lpos: Expected hex digit')} 201 | num = 16*num + hex_to_num(p[pos]) 202 | } 203 | if num > 127 {num -= 256} 204 | } 205 | 257 { 206 | num = int(p[pos] - `0`) 207 | if p[pos+1] != `'` { 208 | pos++ 209 | lpos++ 210 | if !p[pos].is_oct_digit() {parse_err('$line:$lpos: Expected oct digit')} 211 | num = 8*num + int(p[pos] - `0`) 212 | if p[pos+1] != `'` { 213 | pos++ 214 | lpos++ 215 | if !p[pos].is_oct_digit() {parse_err('$line:$lpos: Expected oct digit')} 216 | num = 8*num + int(p[pos] - `0`) 217 | } 218 | } 219 | if num > 255 {parse_err('$line:$lpos: Octal out of range')} 220 | if num > 127 {num -= 256} 221 | } 222 | else {} 223 | } 224 | pos++ 225 | lpos++ 226 | } else { 227 | num = int(p[pos-1]) 228 | } 229 | tokens << new_token(.num, num.str(), line, lpos) 230 | if p[pos] != `'` { 231 | got := p[pos].str() 232 | unexp_err(tokens.last(), 'Expected \' but got $got') 233 | } 234 | pos++ 235 | lpos++ 236 | continue 237 | } 238 | 239 | if p[pos].is_digit() { 240 | start_pos := pos 241 | mut is_octal := false 242 | if p[pos] == `0` { 243 | pos++ 244 | lpos++ 245 | if p[pos] == `x` { 246 | pos++ 247 | lpos++ 248 | for pos < p.len && p[pos].is_hex_digit() { 249 | pos++ 250 | lpos++ 251 | } 252 | } else if p[pos].is_oct_digit() { 253 | is_octal = true 254 | for pos < p.len && p[pos].is_oct_digit() { 255 | pos++ 256 | lpos++ 257 | } 258 | } 259 | } else { 260 | for pos < p.len && p[pos].is_digit() { 261 | pos++ 262 | lpos++ 263 | } 264 | } 265 | tokens << new_token(.num, if is_octal {'0o'} else {''} + p[start_pos..pos], line, lpos) 266 | continue 267 | } 268 | 269 | if p[pos].is_letter() || p[pos] == `_` { 270 | start_pos := pos 271 | for pos < p.len && (p[pos].is_letter() || p[pos] == `_` || p[pos].is_digit()) { 272 | pos++ 273 | lpos++ 274 | } 275 | tokens << new_token(.ident, p[start_pos..pos], line, lpos) 276 | continue 277 | } 278 | 279 | parse_err('$line:$lpos: Cannot tokenize') 280 | cont: 281 | } 282 | 283 | tokens << new_token(.eof, '', line, lpos) 284 | return tokens 285 | } 286 | 287 | -------------------------------------------------------------------------------- /src/type.v: -------------------------------------------------------------------------------- 1 | module src 2 | 3 | const ( 4 | Types = ['int', 'long', 'short', 'char', 'struct', 'union', 'void', 'unsigned', 'signed', '_Bool'] 5 | ) 6 | 7 | struct Type { 8 | mut: 9 | kind []Typekind 10 | suffix []int 11 | strc []&Struct 12 | func []&Funcarg 13 | } 14 | 15 | enum Typekind { 16 | void 17 | int 18 | char 19 | short 20 | long 21 | ll 22 | uint 23 | uchar 24 | ushort 25 | ulong 26 | ull 27 | ptr 28 | ary 29 | strc 30 | func 31 | bool 32 | } 33 | 34 | fn (p mut Parser) consume_type() (bool, &Type, string) { 35 | is_typ, mut typ := p.consume_type_base() 36 | if !is_typ { 37 | return false, typ, '' 38 | } 39 | typb, name := p.consume_type_body() 40 | typ.merge(typb) 41 | if name == '' { 42 | p.token_err('There must be name in the definition') 43 | } 44 | p.check_func_typ(typ) 45 | return true, typ, name 46 | } 47 | 48 | fn (p mut Parser) consume_type_allow_no_ident() (bool, &Type, string) { 49 | is_typ, mut typ := p.consume_type_base() 50 | if !is_typ { 51 | return false, typ, '' 52 | } 53 | typb, name := p.consume_type_body() 54 | typ.merge(typb) 55 | p.check_func_typ(typ) 56 | return true, typ, name 57 | } 58 | 59 | fn (p mut Parser) consume_type_body() (&Type, string) { 60 | mut typ := p.consume_type_front() 61 | mut name := '' 62 | if !p.look_for_bracket() && !p.look_for_bracket_with_type() && p.consume('(') { 63 | typb, str := p.consume_type_body() 64 | p.consume(')') 65 | name = str 66 | typ.merge(p.consume_type_back()) 67 | typ.merge(typb) 68 | } else { 69 | _, name = p.consume_ident() 70 | typ.merge(p.consume_type_back()) 71 | } 72 | return typ, name 73 | } 74 | 75 | fn (p mut Parser) consume_type_nostring() (bool, &Type) { 76 | is_typ, mut typ := p.consume_type_base() 77 | if !is_typ { 78 | return false, typ 79 | } 80 | typ.merge(p.consume_type_body_nostring()) 81 | p.check_func_typ(typ) 82 | return true, typ 83 | } 84 | 85 | fn (p mut Parser) consume_type_body_nostring() &Type { 86 | mut typ := p.consume_type_front() 87 | if !p.look_for_bracket() && !p.look_for_bracket_with_type() && p.consume('(') { 88 | typb := p.consume_type_body_nostring() 89 | p.consume(')') 90 | typ.merge(p.consume_type_back()) 91 | typ.merge(typb) 92 | } else { 93 | typ.merge(p.consume_type_back()) 94 | } 95 | return typ 96 | } 97 | 98 | fn (p mut Parser) consume_type_base() (bool, &Type) { 99 | mut token := p.tokens[p.pos] 100 | mut typ := &Type{} 101 | for p.consume('const') { 102 | token = p.tokens[p.pos] 103 | } 104 | is_lvar, lvar, _ := p.find_lvar(token.str) 105 | if token.kind != .reserved || !token.str in Types { 106 | if is_lvar && lvar.is_type { 107 | p.pos++ 108 | for p.consume('const') {} 109 | return true, lvar.typ.clone() 110 | } else { 111 | typ.kind << Typekind.int 112 | return false, typ 113 | } 114 | } 115 | is_signed := p.consume('signed') 116 | is_unsigned := p.consume('unsigned') 117 | if (is_signed && is_unsigned) || (is_unsigned && p.consume('signed')) { 118 | p.token_err('Type cannot be signed and unsigned') 119 | } 120 | if is_signed || is_unsigned { 121 | token = p.tokens[p.pos] 122 | } 123 | for p.consume('const') { 124 | token = p.tokens[p.pos] 125 | } 126 | if token.str == 'struct' { 127 | if is_signed || is_unsigned { 128 | p.token_err('Struct cannot be signed or unsigned') 129 | } 130 | p.pos++ 131 | typ = p.consume_type_struct() 132 | } else if token.str == 'union' { 133 | if is_signed || is_unsigned { 134 | p.token_err('Union cannot be signed or unsigned') 135 | } 136 | p.pos++ 137 | typ = p.consume_type_union() 138 | } else if token.str == '_Bool' { 139 | if is_signed || is_unsigned { 140 | p.token_err('_Bool cannot be signed or unsigned') 141 | } 142 | p.pos++ 143 | typ.kind << Typekind.bool 144 | } else { 145 | p.pos++ 146 | match token.str { 147 | 'void' { 148 | typ.kind << Typekind.void 149 | } 150 | 'char' { 151 | typ.kind << Typekind.char 152 | } 153 | 'int' { 154 | typ.kind << Typekind.int 155 | } 156 | 'short' { 157 | for p.consume('const') {} 158 | p.consume('int') 159 | typ.kind << Typekind.short 160 | } 161 | 'long' { 162 | for p.consume('const') {} 163 | if p.consume('long') { 164 | typ.kind << Typekind.ll 165 | } else { 166 | typ.kind << Typekind.long 167 | } 168 | for p.consume('const') {} 169 | p.consume('int') 170 | } 171 | else { 172 | p.pos-- 173 | typ.kind << Typekind.int 174 | } 175 | } 176 | if is_unsigned { 177 | old_kind := typ.kind[0] 178 | typ.kind[0] = match old_kind { 179 | .void {Typekind.void} 180 | .int {Typekind.uint} 181 | .char {Typekind.uchar} 182 | .short {Typekind.ushort} 183 | .long {Typekind.ulong} 184 | .ll {Typekind.ull} 185 | else {.void} 186 | } 187 | } 188 | } 189 | for p.consume('const') {} 190 | return true, typ 191 | } 192 | 193 | fn (p mut Parser) consume_type_front() &Type { 194 | mut typ := &Type{} 195 | mut token := p.tokens[p.pos] 196 | for token.kind == .reserved && token.str == '*' { 197 | typ.kind << Typekind.ptr 198 | p.pos++ 199 | token = p.tokens[p.pos] 200 | for p.consume('const') {} 201 | } 202 | return typ 203 | } 204 | 205 | fn (p mut Parser) consume_type_back() &Type { 206 | mut typ := &Type{} 207 | if p.consume('[') { 208 | number := if p.consume(']') { 209 | -1 210 | } else if p.consume('*') { 211 | 0 212 | } else { 213 | p.expect_number() 214 | } 215 | if number != -1 { 216 | p.expect(']') 217 | } 218 | typ = p.consume_type_back() 219 | typ.kind << Typekind.ary 220 | typ.suffix << number 221 | } else if p.consume('(') { 222 | mut first := true 223 | mut paras := []string 224 | mut args := &Funcarg{} 225 | for !p.consume(')') { 226 | if first { 227 | if p.consume('void') { 228 | if p.consume(')') { 229 | break 230 | } 231 | p.pos-- 232 | } 233 | first = false 234 | } else { 235 | p.expect(',') 236 | } 237 | if p.consume('...') { 238 | p.expect(')') 239 | break 240 | } 241 | is_typ, mut argtyp, name := p.consume_type_allow_no_ident() 242 | if !is_typ { 243 | p.token_err('Expected type') 244 | } 245 | if argtyp.kind.last() == .ary { 246 | argtyp = argtyp.reduce() 247 | argtyp.size() 248 | argtyp.kind << Typekind.ptr 249 | } 250 | if argtyp.kind.last() == .func { 251 | argtyp.kind << Typekind.ptr 252 | } 253 | if name in paras { 254 | p.token_err('Parameter `$name` is already declared') 255 | } 256 | if name != '' { 257 | paras << name 258 | } 259 | lvar := p.new_lvar(name, argtyp, 0) 260 | args.args << lvar 261 | } 262 | typ = p.consume_type_back() 263 | typ.kind << Typekind.func 264 | typ.func << args 265 | } 266 | return typ 267 | } 268 | 269 | fn (p mut Parser) expect_type() string { 270 | token := p.tokens[p.pos] 271 | if token.kind != .reserved || !token.str in Types { 272 | unexp_err(token, 'Expected type but got $token.str') 273 | } 274 | p.pos++ 275 | return token.str 276 | } 277 | 278 | fn (p Parser) look_for_bracket() bool { 279 | if !p.look_for('(') {return false} 280 | if p.tokens[p.pos+1].kind == .reserved && p.tokens[p.pos+1].str == ')' { 281 | return true 282 | } 283 | return false 284 | } 285 | 286 | fn (p Parser) look_for_bracket_with_type() bool { 287 | if !p.look_for('(') {return false} 288 | if p.tokens[p.pos+1].kind in [.reserved, .ident] { 289 | str := p.tokens[p.pos+1].str 290 | if str in Types { 291 | return true 292 | } else { 293 | is_lvar, lvar, _ := p.find_lvar(str) 294 | if is_lvar && lvar.is_type { 295 | return true 296 | } 297 | } 298 | } 299 | return false 300 | } 301 | 302 | fn (p mut Parser) consume_type_struct() &Type { 303 | mut typ := &Type{kind:[Typekind.strc]} 304 | is_ident, name := p.consume_ident() 305 | mut is_protoed := false 306 | if is_ident { 307 | is_struct, mut strc, is_curbl := p.find_struct(name) 308 | if is_struct { 309 | if is_curbl && strc.is_defined { 310 | if p.consume('{') { 311 | p.token_err('struct/union $name is already declared in the block') 312 | } else if strc.kind != .strc { 313 | p.token_err('`$name` is not struct') 314 | } 315 | typ.strc << strc 316 | return typ 317 | } 318 | if p.consume('{') { 319 | is_protoed = is_curbl && !strc.is_defined 320 | if is_protoed && strc.kind != .strc { 321 | p.token_err('`$name` is not struct') 322 | } 323 | } else { 324 | if strc.kind != .strc { 325 | p.token_err('`$name` is not struct') 326 | } 327 | typ.strc << strc 328 | return typ 329 | } 330 | } else { 331 | if !p.consume('{') { 332 | strc2 := &Struct{name:name, kind:.strc} 333 | if p.curbl.len == 0 { 334 | p.glstrc[name] = strc2 335 | } else { 336 | mut curbl := p.curbl.last() 337 | curbl.structs[name] = strc2 338 | } 339 | typ.strc << strc2 340 | return typ 341 | } 342 | } 343 | } else { 344 | p.expect('{') 345 | } 346 | _, _strc, _ := p.find_struct(name) 347 | mut strc := if is_protoed { 348 | _strc 349 | } else { 350 | &Struct{name:name, kind:.strc} 351 | } 352 | if !is_protoed && name != '' { 353 | if p.curbl.len == 0 { 354 | p.glstrc[name] = strc 355 | } else { 356 | mut curbl := p.curbl.last() 357 | curbl.structs[name] = strc 358 | } 359 | } 360 | mut max_align := 1 361 | for !p.consume('}') { 362 | is_dec, typ_base := p.consume_type_base() 363 | if is_dec { 364 | mut first := true 365 | for !p.consume(';') { 366 | mut typ_child := typ_base.clone() 367 | if first { 368 | first = false 369 | } else { 370 | p.expect(',') 371 | } 372 | typ_child.merge(p.consume_type_front()) 373 | name_child := p.expect_ident() 374 | if name_child in strc.content { 375 | p.token_err('Duplicated member $name_child') 376 | } 377 | typ_child.merge(p.consume_type_back()) 378 | strc.offset = align(strc.offset, typ_child.size_align()) 379 | max_align = if typ_child.size_align() > max_align {typ_child.size_align()} else {max_align} 380 | lvar := &Lvar{name_child, typ_child, false, false, false, false, strc.offset} 381 | strc.offset += typ_child.size() 382 | strc.content[name_child] = lvar 383 | } 384 | } else { 385 | p.token_err('expected type') 386 | } 387 | } 388 | strc.is_defined = true 389 | strc.max_align = max_align 390 | strc.offset = align(strc.offset, max_align) 391 | typ.strc << strc 392 | return typ 393 | } 394 | 395 | fn (p mut Parser) consume_type_union() &Type { 396 | mut typ := &Type{kind:[Typekind.strc]} 397 | is_ident, name := p.consume_ident() 398 | mut is_protoed := false 399 | if is_ident { 400 | is_struct, mut strc, is_curbl := p.find_struct(name) 401 | if is_struct { 402 | if is_curbl && strc.is_defined { 403 | if p.consume('{') { 404 | p.token_err('struct/union $name is already declared in the block') 405 | } else if strc.kind != .unn { 406 | p.token_err('`$name` is not union') 407 | } 408 | typ.strc << strc 409 | return typ 410 | } 411 | if p.consume('{') { 412 | is_protoed = is_curbl && !strc.is_defined 413 | if is_protoed && strc.kind != .unn { 414 | p.token_err('`$name` is not union') 415 | } 416 | } else { 417 | if strc.kind != .unn { 418 | p.token_err('`$name` is not union') 419 | } 420 | typ.strc << strc 421 | return typ 422 | } 423 | } else { 424 | if !p.consume('{') { 425 | strc2 := &Struct{name:name, kind:.strc} 426 | if p.curbl.len == 0 { 427 | p.glstrc[name] = strc2 428 | } else { 429 | mut curbl := p.curbl.last() 430 | curbl.structs[name] = strc2 431 | } 432 | typ.strc << strc2 433 | return typ 434 | } 435 | } 436 | } else { 437 | p.expect('{') 438 | } 439 | _, _strc, _ := p.find_struct(name) 440 | mut strc := if is_protoed { 441 | _strc 442 | } else { 443 | &Struct{name:name, kind:.unn} 444 | } 445 | if !is_protoed && name != '' { 446 | if p.curbl.len == 0 { 447 | p.glstrc[name] = strc 448 | } else { 449 | mut curbl := p.curbl.last() 450 | curbl.structs[name] = strc 451 | } 452 | } 453 | mut max_align := 1 454 | for !p.consume('}') { 455 | is_dec, typ_base := p.consume_type_base() 456 | if is_dec { 457 | mut first := true 458 | for !p.consume(';') { 459 | mut typ_child := typ_base.clone() 460 | if first { 461 | first = false 462 | } else { 463 | p.expect(',') 464 | } 465 | typ_child.merge(p.consume_type_front()) 466 | name_child := p.expect_ident() 467 | if name_child in strc.content { 468 | p.token_err('Duplicated member $name_child') 469 | } 470 | typ_child.merge(p.consume_type_back()) 471 | strc.offset = if typ_child.size() > strc.offset {typ_child.size()} else {strc.offset} 472 | max_align = if typ_child.size_align() > max_align {typ_child.size_align()} else {max_align} 473 | lvar := &Lvar{name_child, typ_child, false, false, false, false, 0} 474 | strc.content[name_child] = lvar 475 | } 476 | } else { 477 | p.token_err('expected type') 478 | } 479 | } 480 | strc.is_defined = true 481 | strc.max_align = max_align 482 | strc.offset = align(strc.offset, max_align) 483 | typ.strc << strc 484 | return typ 485 | } 486 | 487 | fn (p Parser) check_func_typ(_typ &Type) { 488 | mut typ := _typ.clone() 489 | mut is_func := false 490 | for typ.kind.len != 0 { 491 | if is_func && typ.kind.last() in [.func, .ary] { 492 | p.token_err('Function cannot return type `${*typ}`') 493 | } 494 | is_func = typ.kind.last() == .func 495 | typ = typ.reduce() 496 | } 497 | } 498 | 499 | fn align(offset, size int) int { 500 | return (offset+size-1) & ~(size-1) 501 | } 502 | 503 | fn (typ Type) is_unsigned() bool { 504 | kind := typ.kind.last() 505 | if kind in [.uint, .uchar, .ushort, .ulong, .ull, .ptr] { 506 | return true 507 | } 508 | return false 509 | } 510 | 511 | pub fn (typ Type) str() string { 512 | match typ.kind.last() { 513 | .void { return 'void' } 514 | .int { return 'int' } 515 | .char { return 'char' } 516 | .short { return 'short' } 517 | .long { return 'long' } 518 | .ll { return 'long long' } 519 | .uint { return 'unsigned int' } 520 | .uchar { return 'unsigned char' } 521 | .ushort { return 'unsigned short' } 522 | .ulong { return 'unsigned long' } 523 | .ull { return 'unsigned long long' } 524 | .ptr { return '*'+typ.reduce().str() } 525 | .ary { 526 | last := if typ.suffix.last() < 0 {''} else {'$typ.suffix.last()'} 527 | return '[$last]'+typ.reduce().str() 528 | } 529 | .strc { 530 | strc := typ.strc.last() 531 | postfix := match strc.kind { 532 | .strc { 'struct' } 533 | .unn { 'union' } 534 | else { 'something' } 535 | } 536 | name := strc.name 537 | mut members := []string 538 | for i, lvar in strc.content { 539 | members << '$lvar.typ.str() $i;' 540 | } 541 | return '$postfix $name{$members.join('')}' 542 | } //todo 543 | .bool { return '_Bool' } 544 | .func { 545 | args := typ.func.last() 546 | mut strs := []string 547 | for lvar in args.args { 548 | strs << lvar.typ.str() 549 | } 550 | str := strs.join(', ') 551 | return 'fn($str) '+typ.reduce().str() 552 | } 553 | else { parse_err('Something wrong with type') } 554 | } 555 | return '' 556 | } 557 | 558 | fn (typ Type) size() int { 559 | kind := typ.kind.last() 560 | if kind == .void { 561 | parse_err('Cannot use incomplete type `void`') 562 | } 563 | if kind == .strc { 564 | strc := typ.strc.last() 565 | if !strc.is_defined { 566 | parse_err('Incomplete struct $strc.name') 567 | } else { 568 | return strc.offset 569 | } 570 | } 571 | size := match kind { 572 | .bool, .char, .uchar {1} 573 | .short, .ushort {2} 574 | .int, .uint {4} 575 | .long, .ll, .ulong, .ull, .ptr, .func {8} 576 | .ary {typ.suffix.last() * typ.reduce().size()} 577 | else {8} 578 | } 579 | if size < 0 { 580 | parse_err('Cannot use incomplete type `$typ`') 581 | } 582 | return size 583 | } 584 | 585 | fn (typ Type) size_allow_void() int { 586 | if typ.kind.last() in [.void, .func] { 587 | return 1 588 | } else { 589 | return typ.size() 590 | } 591 | } 592 | 593 | fn (typ Type) size_align() int { 594 | if typ.kind.last() == .ary { 595 | return typ.reduce().size_align() 596 | } else if typ.kind.last() == .strc { 597 | return (typ.strc.last()).max_align 598 | } else { 599 | return typ.size() 600 | } 601 | } 602 | 603 | fn (typ Type) reduce() &Type { 604 | mut typ2 := typ.clone() 605 | if typ2.kind.last() == .ary { 606 | typ2.suffix.delete(typ2.suffix.len-1) 607 | } else if typ2.kind.last() == .strc { 608 | typ2.strc.delete(typ2.strc.len-1) 609 | } else if typ2.kind.last() == .func { 610 | typ2.func.delete(typ2.func.len-1) 611 | } 612 | typ2.kind.delete(typ2.kind.len-1) 613 | return typ2 614 | } 615 | 616 | fn (typ Type) clone() &Type { 617 | return &Type{ 618 | kind:typ.kind.clone() 619 | suffix:typ.suffix.clone() 620 | strc:typ.strc.clone() 621 | func:typ.func.clone() 622 | } 623 | } 624 | 625 | fn (typ Type) cast_ary() &Type { 626 | mut typ2 := typ.clone() 627 | if typ.kind.last() != .ary { 628 | return typ2 629 | } 630 | typ2 = typ2.reduce() 631 | typ2.kind << Typekind.ptr 632 | return typ2 633 | } 634 | 635 | fn (typ mut Type) merge(typ2 &Type) { 636 | typ.kind << typ2.kind 637 | typ.suffix << typ2.suffix 638 | typ.strc << typ2.strc 639 | typ.func << typ2.func 640 | } 641 | 642 | fn (typ Type) is_int() bool { 643 | return typ.kind.last() in [.char, .short, .int, .long, .ll, .uchar, .ushort, .uint, .ulong, .ull, .bool] 644 | } 645 | 646 | fn (typ Type) is_ptr() bool { 647 | return typ.kind.last() == .ptr || typ.kind.last() == .ary 648 | } 649 | 650 | fn type_max(typ1, typ2 &Type) &Type { 651 | mut typ := &Type{} 652 | mut mtyp1 := typ1.clone() 653 | mut mtyp2 := typ2.clone() 654 | typ.kind << Typekind.int 655 | if typ1.size() < 4 { 656 | mtyp1 = typ 657 | } 658 | if typ2.size() < 4 { 659 | mtyp2 = typ 660 | } 661 | if mtyp1.size() > mtyp2.size() { 662 | return mtyp1 663 | } else if mtyp1.size() == mtyp2.size() { 664 | if mtyp2.is_unsigned() { 665 | return mtyp2 666 | } 667 | return mtyp1 668 | } else { 669 | return mtyp2 670 | } 671 | } 672 | 673 | fn (node mut Node) add_type() { 674 | if node.kind == .nothing || node.typ != 0 { 675 | return 676 | } 677 | if !isnil(node.cond) {node.cond.add_type()} 678 | if !isnil(node.first) {node.first.add_type()} 679 | if !isnil(node.left) {node.left.add_type()} 680 | if !isnil(node.right) {node.right.add_type()} 681 | 682 | for i in node.code { 683 | mut no := i 684 | no.add_type() 685 | } 686 | 687 | mut typ := &Type{} 688 | 689 | match(node.kind) { 690 | .assign, .calcassign { 691 | node.typ = node.left.typ.clone() 692 | } 693 | .eq, .ne, .gt, .ge, .num { 694 | typ.kind << Typekind.int 695 | node.typ = typ 696 | } 697 | .add, .sub, .mul, .div, .mod, .bitand, .bitor, .bitxor { 698 | bigtyp := type_max(node.left.typ, node.right.typ) 699 | if node.left.typ.is_ptr() || node.right.typ.is_ptr() { 700 | parse_err('Invalid operand type') 701 | } 702 | node.typ = bigtyp.cast_ary() 703 | } 704 | .ifelse { 705 | if node.name == 'stmt' { 706 | return 707 | } 708 | if node.left.typ.kind.last() == .void || node.right.typ.kind.last() == .void { 709 | typ.kind << Typekind.void 710 | node.typ = typ 711 | } else if node.left.typ.kind.last() == .strc { 712 | if node.left.typ.strc.last() != node.right.typ.strc.last() { 713 | parse_err('Incompatible struct in ternary') 714 | } 715 | node.typ = node.left.typ.clone() 716 | } else { 717 | bigtyp := type_max(node.left.typ, node.right.typ) 718 | node.typ = bigtyp.cast_ary() 719 | } 720 | } 721 | .incb, .decb, .incf, .decf, .shl, .shr, .bitnot { 722 | if (node.kind in [.shl, .shr, .bitnot] && node.left.typ.is_ptr()) || (node.kind in [.shl, .shr] && node.right.typ.is_ptr()) { 723 | parse_err('Invalid operand type') 724 | } 725 | node.typ = node.left.typ.cast_ary() 726 | } 727 | .comma { 728 | node.typ = node.right.typ.cast_ary() 729 | } 730 | .call { 731 | typ.kind << Typekind.ulong 732 | node.typ = typ 733 | } 734 | .sizof { 735 | typ.kind << Typekind.ulong 736 | node.typ = typ 737 | } 738 | .deref { 739 | if node.left.typ.is_ptr() { 740 | typ = node.left.typ.reduce() 741 | } else if node.left.typ.kind.last() == .func { 742 | typ = node.left.typ.clone() 743 | } else { 744 | parse_err("Cannot dereference non-pointer type") 745 | } 746 | node.typ = typ 747 | } 748 | .addr { 749 | typ = node.left.typ.clone() 750 | if typ.kind.last() == .ary { 751 | typ = typ.reduce() 752 | } 753 | typ.kind << Typekind.ptr 754 | node.typ = typ 755 | } 756 | .string { 757 | typ.kind << Typekind.char 758 | typ.kind << Typekind.ary 759 | typ.suffix << node.name.len+1 760 | node.typ = typ 761 | } 762 | else {} 763 | } 764 | } 765 | -------------------------------------------------------------------------------- /test.vsh: -------------------------------------------------------------------------------- 1 | fn try(expected int, input string) { 2 | write_file('tmp.c', 'int printf(char*,...);int foo();int bar(int,int);int hw();void alloc4(int**,int,int,int,int);'+input) 3 | system('./vcc tmp.c > tmp.s') 4 | system('gcc -o tmp tmp.s tmp2.o') 5 | actual := system('./tmp')/256 6 | if actual == expected { 7 | println('$input => $actual') 8 | } else { 9 | println('$input => $expected expected, but got $actual') 10 | exit(1) 11 | } 12 | } 13 | fn main(){ 14 | 15 | mut file := create('tmp2.c') or {panic('failed to create tmp2.c')} 16 | file.write(' 17 | extern void *malloc(unsigned long int size); 18 | extern int printf(const char * format,...); 19 | int foo(){return 21;} 20 | int bar(int i, int j){return i+j;} 21 | int hw(){printf("Hello, world!\\n");} 22 | void alloc4(int**p, int a, int b, int c, int d){*p=malloc(16);**p=a;*(*p+1)=b;*(*p+2)=c;*(*p+3)=d;} 23 | ') 24 | file.close() 25 | system('./vcc tmp2.c > tmp2.s') 26 | system('gcc -c -o tmp2.o tmp2.s') 27 | 28 | try(0 , 'int main(){return 0;}') 29 | try(42, 'int main(){return 42;}') 30 | try(21, 'int main(){return 5+20-4;}') 31 | try(41, 'int main(){return 12 + 34 - 5 ;}') 32 | try(47, 'int main(){return 5+6*7;}') 33 | try(15, 'int main(){return 5*(9-6);}') 34 | try(4 , 'int main(){return (3+5)/2;}') 35 | try(7 , 'int main(){return -3+10;}') 36 | try(7 , 'int main(){return -3+ +10;}') 37 | try(7 , 'int main(){return -3- -10;}') 38 | try(12, 'int main(){return -(3+5)+20;}') 39 | try(30, 'int main(){return -3*+5*-2;}') 40 | try(1 , 'int main(){return 1+1==2;}') 41 | try(0 , 'int main(){return 1+1==3;}') 42 | try(1 , 'int main(){return 2>1;}') 43 | try(1 , 'int main(){return 43>=43;}') 44 | try(0 , 'int main(){return (0<1)*2!=2;}') 45 | try(1 , 'int main(){return 1>2==3>=4;}') 46 | try(5 , 'int main(){int foo;int bar;foo=2;bar=4-1;foo=foo+bar;return foo;}') 47 | try(3 , 'int main(){int bar;int foo;foo=2;return bar=4-1;foo=foo+bar;return foo;}') 48 | try(2 , 'int main(){int foo;int bar;foo=bar=2;return foo;}') 49 | try(4 , 'int main(){int returna;returna = 3;int _1_; _1_ = returna + 1; return _1_;}') 50 | try(6 , 'int main(){int ife;ife = 2; if(ife > 5) return ife; else return 6;}') 51 | try(7 , 'int main(){int ife;ife = 7; if(ife > 5) return ife; else return 6;}') 52 | try(23, 'int main(){int a;if(1)a=23; return a;}') 53 | try(34, 'int main(){int hoge;hoge = 3; if(hoge > 6) return 23; else if (hoge>2) return 34; else return 45;}') 54 | try(22, 'int main(){int huga;huga=3;if(huga>1)if(huga<5)return 22;return 4;}') 55 | try(4 , 'int main(){int huga;huga=1;if(huga>1)if(huga<5)return 22;return 4;}') 56 | try(4 , 'int main(){int huga;huga=7;if(huga>1)if(huga<5)return 22;return 4;}') 57 | try(45, 'int main(){int foo;int i;foo = 0; for(i=0; i<10; i=i+1)foo=foo+i;return foo;}') 58 | try(11, 'int main(){int foo;foo = 0; for(;;)if((foo=foo+1)>10)return foo;}') 59 | try(55, 'int main(){int foo;int i;foo = i = 0; while(i<10)foo=foo+(i=i+1);return foo;}') 60 | try(45, 'int main(){int foo;int i;foo = i = 0; while(i<10){foo=foo+i;i=i+1;}return foo;}') 61 | try(15, 'int main(){int foo;int i;foo=0;for(i=0; i<10; i=i+1){if(i-i/2*2==1){foo=foo+1;}else{foo=foo+2;}}return foo;}') 62 | try(21, 'int main(){return foo();}') 63 | try(42, 'int main(){int foo2;foo2=2;return foo()*foo2;}') 64 | try(55, 'int main(){return foo()*bar(2,3)-50;}') 65 | try(48, 'int fuga(),hoge();int main(){return hoge()+fuga();}int hoge(){return 32;}int fuga(){int hoge;hoge=16;return hoge;}') 66 | try(21, 'int fib(int);int main(){return fib(7);}int fib(int n){if(n>1)return fib(n-1)+fib(n-2);else return 1;}') 67 | try(23, 'int hoge(int,int);int main(){return hoge(4,5);}int hoge(int n,int m){if(n>m)return 12;return 23;}') 68 | try(3 , 'int main(){int x;int *y;x=3;y=&x;return *y;}') 69 | try(3 , 'int main(){int x;int y;int *z;x=3;y=5;z=&y+1;return *z;}') 70 | try(3 , 'int main(){int x;int *y;y=&x;*y=3;return x;}') 71 | try(4 , 'int main(){int *p;alloc4(&p, 1, 2, 4, 8);int *q;q=p+2;return *q;}') 72 | try(8 , 'int main(){int *p;alloc4(&p, 1, 2, 4, 8);int *q;q=p+3;return *q;}') 73 | try(4 , 'int main(){return sizeof(1);}') 74 | try(8 , 'int main(){int *x;return sizeof(x);}') 75 | try(4 , 'int main(){int *x;return sizeof(*x);}') 76 | try(4 , 'int val,hoge();int main(){hoge();return val;}int hoge(){int hoge=4; val = hoge;}') 77 | try(4 , 'int main(){char a=1;short int b=2; int c=3; long d=4; long long int e=5; return d;}') 78 | try(111,'int main(){char *a="hgoe"; printf(a); printf("hgoee"); return a[2];}') 79 | try(12, 'int main(){return (3%2)?12:5;}') 80 | try(5 , 'int main(){return 0+0?12:5;}') 81 | try(1 , 'int main(){int a=1;{int a=2;{int a=3;}}return a;}') 82 | try(2 , 'int main(){int a=1;{int a=2;{int a=3;}return a;}}') 83 | try(3 , 'int main(){int a=1;{int a=2;{int a=3;return a;}}}') 84 | try(3 , 'int main(){int a=1,b=2,c=3,d=4;return c;}') 85 | try(45, 'int main(){int a=0; for(int i=0; i<10; i++)a=a+i;return a;}') 86 | try(3 , 'int main(){for(;;)break;return 3;}') 87 | try(45, 'int main(){int a=0; for(int i=0;;i++){if(i<10){a=a+i;continue;}else{break;}}return a;}') 88 | try(10, 'int main(){int a=0; while(++a<10);return a;}') 89 | try(55, 'int main(){int a=0, i=0; do{i++;a=a+i;}while(i<10);return a;}') 90 | try(54, 'int main(){int a=0;for(int i=0;i<10;i++){for(int j=0;j<10;j++){a=a+i;if(a>52){goto hoge;}}}hoge:return a;}') 91 | try(1 , 'int main(){return \'b\' - \'\\n\' == \'X\';}') 92 | try(10, 'int pluser();int main(){int a=0;for(int i=0;i<10;i++)a=pluser();return a;}int pluser(){static int hoge;hoge++;return hoge;}') 93 | try(0 , 'int main(){return ~-!0;}') 94 | 95 | println('OK') 96 | } 97 | -------------------------------------------------------------------------------- /vcc.v: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | import ( 4 | os 5 | src 6 | ) 7 | 8 | fn main(){ 9 | args := os.args 10 | mut program := '' 11 | if args.len < 2 { 12 | eprintln('The number of arguments is not correct.') 13 | exit(1) 14 | } 15 | if args[1] == '-' { 16 | if args.len < 3 { 17 | eprintln('There is no input string') 18 | exit(1) 19 | } 20 | program = args[2] 21 | } else { 22 | cont := os.read_file(args[1])? 23 | program = cont 24 | } 25 | 26 | mut parser := src.Parser{ 27 | tokens:src.tokenize(program) 28 | progstr:program 29 | pos:0 30 | statics:1972 31 | curfn:0 32 | } 33 | parser.program() 34 | parser.gen_main() 35 | } 36 | --------------------------------------------------------------------------------