| ... | @@ -164,6 +164,9 @@ pub const Parser = struct { | ... | @@ -164,6 +164,9 @@ pub const Parser = struct { |
| 164 | WhileContinueExpr: &?&ast.Node, | 164 | WhileContinueExpr: &?&ast.Node, |
| 165 | Statement: &ast.NodeBlock, | 165 | Statement: &ast.NodeBlock, |
| 166 | Semicolon: &const &const ast.Node, | 166 | Semicolon: &const &const ast.Node, |
| | 167 | AsmOutputItems: &ArrayList(ast.NodeAsm.AsmOutput), |
| | 168 | AsmInputItems: &ArrayList(ast.NodeAsm.AsmInput), |
| | 169 | AsmClopperItems: &ArrayList(&ast.NodeStringLiteral), |
| 167 | ExprListItemOrEnd: ExprListCtx, | 170 | ExprListItemOrEnd: ExprListCtx, |
| 168 | ExprListCommaOrEnd: ExprListCtx, | 171 | ExprListCommaOrEnd: ExprListCtx, |
| 169 | FieldInitListItemOrEnd: ListSave(&ast.NodeFieldInitializer), | 172 | FieldInitListItemOrEnd: ListSave(&ast.NodeFieldInitializer), |
| ... | @@ -1488,7 +1491,44 @@ pub const Parser = struct { | ... | @@ -1488,7 +1491,44 @@ pub const Parser = struct { |
| 1488 | continue; | 1491 | continue; |
| 1489 | }, | 1492 | }, |
| 1490 | Token.Id.Keyword_asm => { | 1493 | Token.Id.Keyword_asm => { |
| 1491 | @panic("TODO: inline asm"); | 1494 | const is_volatile = blk: { |
| | 1495 | const volatile_token = self.getNextToken(); |
| | 1496 | if (volatile_token.id != Token.Id.Keyword_volatile) { |
| | 1497 | self.putBackToken(volatile_token); |
| | 1498 | break :blk false; |
| | 1499 | } |
| | 1500 | break :blk true; |
| | 1501 | }; |
| | 1502 | _ = (try self.eatToken(&stack, Token.Id.LParen)) ?? continue; |
| | 1503 | const template = (try self.eatToken(&stack, Token.Id.StringLiteral)) ?? continue; |
| | 1504 | // TODO parse template |
| | 1505 | |
| | 1506 | const node = try arena.create(ast.NodeAsm); |
| | 1507 | *node = ast.NodeAsm { |
| | 1508 | .base = self.initNode(ast.Node.Id.Asm), |
| | 1509 | .asm_token = token, |
| | 1510 | .is_volatile = is_volatile, |
| | 1511 | .template = template, |
| | 1512 | //.tokens = ArrayList(ast.NodeAsm.AsmToken).init(arena), |
| | 1513 | .outputs = ArrayList(ast.NodeAsm.AsmOutput).init(arena), |
| | 1514 | .inputs = ArrayList(ast.NodeAsm.AsmInput).init(arena), |
| | 1515 | .cloppers = ArrayList(&ast.NodeStringLiteral).init(arena), |
| | 1516 | .rparen = undefined, |
| | 1517 | }; |
| | 1518 | dest_ptr.store(&node.base); |
| | 1519 | |
| | 1520 | stack.append(State { |
| | 1521 | .ExpectTokenSave = ExpectTokenSave { |
| | 1522 | .id = Token.Id.RParen, |
| | 1523 | .ptr = &node.rparen, |
| | 1524 | } |
| | 1525 | }) catch unreachable; |
| | 1526 | try stack.append(State { .AsmClopperItems = &node.cloppers }); |
| | 1527 | try stack.append(State { .IfToken = Token.Id.Colon }); |
| | 1528 | try stack.append(State { .AsmInputItems = &node.inputs }); |
| | 1529 | try stack.append(State { .IfToken = Token.Id.Colon }); |
| | 1530 | try stack.append(State { .AsmOutputItems = &node.outputs }); |
| | 1531 | try stack.append(State { .IfToken = Token.Id.Colon }); |
| 1492 | }, | 1532 | }, |
| 1493 | Token.Id.Keyword_if => { | 1533 | Token.Id.Keyword_if => { |
| 1494 | const node = try arena.create(ast.NodeIf); | 1534 | const node = try arena.create(ast.NodeIf); |
| ... | @@ -1621,6 +1661,84 @@ pub const Parser = struct { | ... | @@ -1621,6 +1661,84 @@ pub const Parser = struct { |
| 1621 | } | 1661 | } |
| 1622 | }, | 1662 | }, |
| 1623 | | 1663 | |
| | 1664 | |
| | 1665 | State.AsmOutputItems => |items| { |
| | 1666 | const lbracket = self.getNextToken(); |
| | 1667 | if (lbracket.id != Token.Id.LBracket) { |
| | 1668 | self.putBackToken(lbracket); |
| | 1669 | continue; |
| | 1670 | } |
| | 1671 | |
| | 1672 | stack.append(State { .AsmOutputItems = items }) catch unreachable; |
| | 1673 | try stack.append(State { .IfToken = Token.Id.Comma }); |
| | 1674 | |
| | 1675 | const symbolic_name = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue; |
| | 1676 | _ = (try self.eatToken(&stack, Token.Id.RBracket)) ?? continue; |
| | 1677 | const constraint = (try self.eatToken(&stack, Token.Id.StringLiteral)) ?? continue; |
| | 1678 | |
| | 1679 | _ = (try self.eatToken(&stack, Token.Id.LParen)) ?? continue; |
| | 1680 | try stack.append(State { .ExpectToken = Token.Id.RParen }); |
| | 1681 | |
| | 1682 | const res = try items.addOne(); |
| | 1683 | *res = ast.NodeAsm.AsmOutput { |
| | 1684 | .symbolic_name = symbolic_name, |
| | 1685 | .constraint = constraint, |
| | 1686 | .variable_name = null, |
| | 1687 | .return_type = null, |
| | 1688 | }; |
| | 1689 | const symbol_or_arrow = self.getNextToken(); |
| | 1690 | switch (symbol_or_arrow.id) { |
| | 1691 | Token.Id.Identifier => res.variable_name = symbol_or_arrow, |
| | 1692 | Token.Id.Arrow => { |
| | 1693 | try stack.append(State { .TypeExprBegin = DestPtr { .NullableField = &res.return_type } }); |
| | 1694 | }, |
| | 1695 | else => { |
| | 1696 | try self.parseError(&stack, symbol_or_arrow, "expected '->' or {}, found {}", |
| | 1697 | @tagName(Token.Id.Identifier), |
| | 1698 | @tagName(symbol_or_arrow.id)); |
| | 1699 | continue; |
| | 1700 | }, |
| | 1701 | } |
| | 1702 | }, |
| | 1703 | |
| | 1704 | State.AsmInputItems => |items| { |
| | 1705 | const lbracket = self.getNextToken(); |
| | 1706 | if (lbracket.id != Token.Id.LBracket) { |
| | 1707 | self.putBackToken(lbracket); |
| | 1708 | continue; |
| | 1709 | } |
| | 1710 | |
| | 1711 | stack.append(State { .AsmInputItems = items }) catch unreachable; |
| | 1712 | try stack.append(State { .IfToken = Token.Id.Comma }); |
| | 1713 | |
| | 1714 | const symbolic_name = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue; |
| | 1715 | _ = (try self.eatToken(&stack, Token.Id.RBracket)) ?? continue; |
| | 1716 | const constraint = (try self.eatToken(&stack, Token.Id.StringLiteral)) ?? continue; |
| | 1717 | |
| | 1718 | _ = (try self.eatToken(&stack, Token.Id.LParen)) ?? continue; |
| | 1719 | try stack.append(State { .ExpectToken = Token.Id.RParen }); |
| | 1720 | |
| | 1721 | const res = try items.addOne(); |
| | 1722 | *res = ast.NodeAsm.AsmInput { |
| | 1723 | .symbolic_name = symbolic_name, |
| | 1724 | .constraint = constraint, |
| | 1725 | .expr = undefined, |
| | 1726 | }; |
| | 1727 | try stack.append(State { .Expression = DestPtr { .Field = &res.expr } }); |
| | 1728 | }, |
| | 1729 | |
| | 1730 | State.AsmClopperItems => |items| { |
| | 1731 | const string = self.getNextToken(); |
| | 1732 | if (string.id != Token.Id.StringLiteral) { |
| | 1733 | self.putBackToken(string); |
| | 1734 | continue; |
| | 1735 | } |
| | 1736 | |
| | 1737 | try items.append(try self.createStringLiteral(arena, string)); |
| | 1738 | stack.append(State { .AsmClopperItems = items }) catch unreachable; |
| | 1739 | try stack.append(State { .IfToken = Token.Id.Comma }); |
| | 1740 | }, |
| | 1741 | |
| 1624 | State.ExprListItemOrEnd => |list_state| { | 1742 | State.ExprListItemOrEnd => |list_state| { |
| 1625 | var token = self.getNextToken(); | 1743 | var token = self.getNextToken(); |
| 1626 | | 1744 | |
| ... | @@ -3675,6 +3793,24 @@ pub const Parser = struct { | ... | @@ -3675,6 +3793,24 @@ pub const Parser = struct { |
| 3675 | try stack.append(RenderState { .Expression = if_node.condition }); | 3793 | try stack.append(RenderState { .Expression = if_node.condition }); |
| 3676 | try stack.append(RenderState { .Text = "(" }); | 3794 | try stack.append(RenderState { .Text = "(" }); |
| 3677 | }, | 3795 | }, |
| | 3796 | ast.Node.Id.Asm => { |
| | 3797 | const asm_node = @fieldParentPtr(ast.NodeAsm, "base", base); |
| | 3798 | try stream.print("{} ", self.tokenizer.getTokenSlice(asm_node.asm_token)); |
| | 3799 | |
| | 3800 | if (asm_node.is_volatile) { |
| | 3801 | try stream.write("volatile "); |
| | 3802 | } |
| | 3803 | |
| | 3804 | try stream.print("({}", self.tokenizer.getTokenSlice(asm_node.template)); |
| | 3805 | |
| | 3806 | try stack.append(RenderState { .Text = ")" }); |
| | 3807 | @panic("TODO: Render asm"); |
| | 3808 | //\\ return asm volatile ("syscall" |
| | 3809 | //\\ : [ret] "={rax}" (-> usize) |
| | 3810 | //\\ : [number] "{rax}" (number), |
| | 3811 | //\\ [arg1] "{rdi}" (arg1) |
| | 3812 | //\\ : "rcx", "r11"); |
| | 3813 | },, |
| 3678 | | 3814 | |
| 3679 | ast.Node.Id.StructField, | 3815 | ast.Node.Id.StructField, |
| 3680 | ast.Node.Id.UnionTag, | 3816 | ast.Node.Id.UnionTag, |