std.zig.parser now parses asm expressions
* We cannot render asm expressions yetmaster
parent
aa552633cc
commit
a09bb408a2
|
@ -47,6 +47,7 @@ pub const Node = struct {
|
|||
NullLiteral,
|
||||
UndefinedLiteral,
|
||||
ThisLiteral,
|
||||
Asm,
|
||||
Unreachable,
|
||||
ErrorType,
|
||||
BuiltinCall,
|
||||
|
@ -94,6 +95,7 @@ pub const Node = struct {
|
|||
Id.NullLiteral => @fieldParentPtr(NodeNullLiteral, "base", base).iterate(index),
|
||||
Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).iterate(index),
|
||||
Id.ThisLiteral => @fieldParentPtr(NodeThisLiteral, "base", base).iterate(index),
|
||||
Id.Asm => @fieldParentPtr(NodeAsm, "base", base).iterate(index),
|
||||
Id.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).iterate(index),
|
||||
Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).iterate(index),
|
||||
Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).iterate(index),
|
||||
|
@ -143,6 +145,7 @@ pub const Node = struct {
|
|||
Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).firstToken(),
|
||||
Id.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).firstToken(),
|
||||
Id.ThisLiteral => @fieldParentPtr(NodeThisLiteral, "base", base).firstToken(),
|
||||
Id.Asm => @fieldParentPtr(NodeAsm, "base", base).firstToken(),
|
||||
Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).firstToken(),
|
||||
Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).firstToken(),
|
||||
Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).firstToken(),
|
||||
|
@ -190,6 +193,7 @@ pub const Node = struct {
|
|||
Id.NullLiteral => @fieldParentPtr(NodeNullLiteral, "base", base).lastToken(),
|
||||
Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).lastToken(),
|
||||
Id.ThisLiteral => @fieldParentPtr(NodeThisLiteral, "base", base).lastToken(),
|
||||
Id.Asm => @fieldParentPtr(NodeAsm, "base", base).lastToken(),
|
||||
Id.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).lastToken(),
|
||||
Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).lastToken(),
|
||||
Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).lastToken(),
|
||||
|
@ -1512,6 +1516,43 @@ pub const NodeThisLiteral = struct {
|
|||
}
|
||||
};
|
||||
|
||||
pub const NodeAsm = struct {
|
||||
base: Node,
|
||||
asm_token: Token,
|
||||
is_volatile: bool,
|
||||
template: Token,
|
||||
//tokens: ArrayList(AsmToken),
|
||||
outputs: ArrayList(AsmOutput),
|
||||
inputs: ArrayList(AsmInput),
|
||||
cloppers: ArrayList(&NodeStringLiteral),
|
||||
rparen: Token,
|
||||
|
||||
const AsmOutput = struct {
|
||||
symbolic_name: Token,
|
||||
constraint: Token,
|
||||
variable_name: ?Token,
|
||||
return_type: ?&Node,
|
||||
};
|
||||
|
||||
const AsmInput = struct {
|
||||
symbolic_name: Token,
|
||||
constraint: Token,
|
||||
expr: &Node,
|
||||
};
|
||||
|
||||
pub fn iterate(self: &NodeAsm, index: usize) ?&Node {
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn firstToken(self: &NodeAsm) Token {
|
||||
return self.asm_token;
|
||||
}
|
||||
|
||||
pub fn lastToken(self: &NodeAsm) Token {
|
||||
return self.rparen;
|
||||
}
|
||||
};
|
||||
|
||||
pub const NodeUnreachable = struct {
|
||||
base: Node,
|
||||
token: Token,
|
||||
|
|
|
@ -164,6 +164,9 @@ pub const Parser = struct {
|
|||
WhileContinueExpr: &?&ast.Node,
|
||||
Statement: &ast.NodeBlock,
|
||||
Semicolon: &const &const ast.Node,
|
||||
AsmOutputItems: &ArrayList(ast.NodeAsm.AsmOutput),
|
||||
AsmInputItems: &ArrayList(ast.NodeAsm.AsmInput),
|
||||
AsmClopperItems: &ArrayList(&ast.NodeStringLiteral),
|
||||
ExprListItemOrEnd: ExprListCtx,
|
||||
ExprListCommaOrEnd: ExprListCtx,
|
||||
FieldInitListItemOrEnd: ListSave(&ast.NodeFieldInitializer),
|
||||
|
@ -1488,7 +1491,44 @@ pub const Parser = struct {
|
|||
continue;
|
||||
},
|
||||
Token.Id.Keyword_asm => {
|
||||
@panic("TODO: inline asm");
|
||||
const is_volatile = blk: {
|
||||
const volatile_token = self.getNextToken();
|
||||
if (volatile_token.id != Token.Id.Keyword_volatile) {
|
||||
self.putBackToken(volatile_token);
|
||||
break :blk false;
|
||||
}
|
||||
break :blk true;
|
||||
};
|
||||
_ = (try self.eatToken(&stack, Token.Id.LParen)) ?? continue;
|
||||
const template = (try self.eatToken(&stack, Token.Id.StringLiteral)) ?? continue;
|
||||
// TODO parse template
|
||||
|
||||
const node = try arena.create(ast.NodeAsm);
|
||||
*node = ast.NodeAsm {
|
||||
.base = self.initNode(ast.Node.Id.Asm),
|
||||
.asm_token = token,
|
||||
.is_volatile = is_volatile,
|
||||
.template = template,
|
||||
//.tokens = ArrayList(ast.NodeAsm.AsmToken).init(arena),
|
||||
.outputs = ArrayList(ast.NodeAsm.AsmOutput).init(arena),
|
||||
.inputs = ArrayList(ast.NodeAsm.AsmInput).init(arena),
|
||||
.cloppers = ArrayList(&ast.NodeStringLiteral).init(arena),
|
||||
.rparen = undefined,
|
||||
};
|
||||
dest_ptr.store(&node.base);
|
||||
|
||||
stack.append(State {
|
||||
.ExpectTokenSave = ExpectTokenSave {
|
||||
.id = Token.Id.RParen,
|
||||
.ptr = &node.rparen,
|
||||
}
|
||||
}) catch unreachable;
|
||||
try stack.append(State { .AsmClopperItems = &node.cloppers });
|
||||
try stack.append(State { .IfToken = Token.Id.Colon });
|
||||
try stack.append(State { .AsmInputItems = &node.inputs });
|
||||
try stack.append(State { .IfToken = Token.Id.Colon });
|
||||
try stack.append(State { .AsmOutputItems = &node.outputs });
|
||||
try stack.append(State { .IfToken = Token.Id.Colon });
|
||||
},
|
||||
Token.Id.Keyword_if => {
|
||||
const node = try arena.create(ast.NodeIf);
|
||||
|
@ -1621,6 +1661,84 @@ pub const Parser = struct {
|
|||
}
|
||||
},
|
||||
|
||||
|
||||
State.AsmOutputItems => |items| {
|
||||
const lbracket = self.getNextToken();
|
||||
if (lbracket.id != Token.Id.LBracket) {
|
||||
self.putBackToken(lbracket);
|
||||
continue;
|
||||
}
|
||||
|
||||
stack.append(State { .AsmOutputItems = items }) catch unreachable;
|
||||
try stack.append(State { .IfToken = Token.Id.Comma });
|
||||
|
||||
const symbolic_name = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue;
|
||||
_ = (try self.eatToken(&stack, Token.Id.RBracket)) ?? continue;
|
||||
const constraint = (try self.eatToken(&stack, Token.Id.StringLiteral)) ?? continue;
|
||||
|
||||
_ = (try self.eatToken(&stack, Token.Id.LParen)) ?? continue;
|
||||
try stack.append(State { .ExpectToken = Token.Id.RParen });
|
||||
|
||||
const res = try items.addOne();
|
||||
*res = ast.NodeAsm.AsmOutput {
|
||||
.symbolic_name = symbolic_name,
|
||||
.constraint = constraint,
|
||||
.variable_name = null,
|
||||
.return_type = null,
|
||||
};
|
||||
const symbol_or_arrow = self.getNextToken();
|
||||
switch (symbol_or_arrow.id) {
|
||||
Token.Id.Identifier => res.variable_name = symbol_or_arrow,
|
||||
Token.Id.Arrow => {
|
||||
try stack.append(State { .TypeExprBegin = DestPtr { .NullableField = &res.return_type } });
|
||||
},
|
||||
else => {
|
||||
try self.parseError(&stack, symbol_or_arrow, "expected '->' or {}, found {}",
|
||||
@tagName(Token.Id.Identifier),
|
||||
@tagName(symbol_or_arrow.id));
|
||||
continue;
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
State.AsmInputItems => |items| {
|
||||
const lbracket = self.getNextToken();
|
||||
if (lbracket.id != Token.Id.LBracket) {
|
||||
self.putBackToken(lbracket);
|
||||
continue;
|
||||
}
|
||||
|
||||
stack.append(State { .AsmInputItems = items }) catch unreachable;
|
||||
try stack.append(State { .IfToken = Token.Id.Comma });
|
||||
|
||||
const symbolic_name = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue;
|
||||
_ = (try self.eatToken(&stack, Token.Id.RBracket)) ?? continue;
|
||||
const constraint = (try self.eatToken(&stack, Token.Id.StringLiteral)) ?? continue;
|
||||
|
||||
_ = (try self.eatToken(&stack, Token.Id.LParen)) ?? continue;
|
||||
try stack.append(State { .ExpectToken = Token.Id.RParen });
|
||||
|
||||
const res = try items.addOne();
|
||||
*res = ast.NodeAsm.AsmInput {
|
||||
.symbolic_name = symbolic_name,
|
||||
.constraint = constraint,
|
||||
.expr = undefined,
|
||||
};
|
||||
try stack.append(State { .Expression = DestPtr { .Field = &res.expr } });
|
||||
},
|
||||
|
||||
State.AsmClopperItems => |items| {
|
||||
const string = self.getNextToken();
|
||||
if (string.id != Token.Id.StringLiteral) {
|
||||
self.putBackToken(string);
|
||||
continue;
|
||||
}
|
||||
|
||||
try items.append(try self.createStringLiteral(arena, string));
|
||||
stack.append(State { .AsmClopperItems = items }) catch unreachable;
|
||||
try stack.append(State { .IfToken = Token.Id.Comma });
|
||||
},
|
||||
|
||||
State.ExprListItemOrEnd => |list_state| {
|
||||
var token = self.getNextToken();
|
||||
|
||||
|
@ -3675,6 +3793,24 @@ pub const Parser = struct {
|
|||
try stack.append(RenderState { .Expression = if_node.condition });
|
||||
try stack.append(RenderState { .Text = "(" });
|
||||
},
|
||||
ast.Node.Id.Asm => {
|
||||
const asm_node = @fieldParentPtr(ast.NodeAsm, "base", base);
|
||||
try stream.print("{} ", self.tokenizer.getTokenSlice(asm_node.asm_token));
|
||||
|
||||
if (asm_node.is_volatile) {
|
||||
try stream.write("volatile ");
|
||||
}
|
||||
|
||||
try stream.print("({}", self.tokenizer.getTokenSlice(asm_node.template));
|
||||
|
||||
try stack.append(RenderState { .Text = ")" });
|
||||
@panic("TODO: Render asm");
|
||||
//\\ return asm volatile ("syscall"
|
||||
//\\ : [ret] "={rax}" (-> usize)
|
||||
//\\ : [number] "{rax}" (number),
|
||||
//\\ [arg1] "{rdi}" (arg1)
|
||||
//\\ : "rcx", "r11");
|
||||
},,
|
||||
|
||||
ast.Node.Id.StructField,
|
||||
ast.Node.Id.UnionTag,
|
||||
|
|
Loading…
Reference in New Issue