Skip to content

Commit a93a58c

Browse files
committed
interpreter: widen instructions, immediates
1 parent ef34832 commit a93a58c

11 files changed

Lines changed: 543 additions & 476 deletions

File tree

interpreter/src/ir.rs

Lines changed: 190 additions & 199 deletions
Large diffs are not rendered by default.

interpreter/src/ir/lower.rs

Lines changed: 234 additions & 176 deletions
Large diffs are not rendered by default.

interpreter/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
//
33
// For the full copyright and license information, please view the LICENSE
44
// files that was distributed with this source code.
5-
65
#![allow(dead_code)]
76

87
pub(crate) mod ir;

interpreter/src/vm.rs

Lines changed: 91 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use parser::{Command, Identifier, Redirection};
1919

2020
use crate::{
2121
ir::{
22-
Instruction, Label, MaybeImm, NonLocal, Reg,
22+
Instruction, Label, NonLocal, Reg,
2323
lower::{Bytecode, Code},
2424
},
2525
types::Value,
@@ -32,7 +32,6 @@ pub enum ExecMode {
3232
Posix,
3333
}
3434

35-
#[derive(Debug)]
3635
pub struct Interpreter<'a> {
3736
arena: &'a Bump,
3837
bc: Bytecode<'a>,
@@ -121,20 +120,25 @@ impl<'a> Consts<'a> {
121120
impl Interpreter<'_> {
122121
pub fn run(&mut self) {
123122
macro_rules! rx {
124-
($self:expr, $dest:expr, $src:ident, $e:expr) => {{
125-
rx!($self, $src);
123+
($self:expr, $dest:expr, $src:ident: $ty:ident, $e:expr) => {{
124+
rx!($self, $src: $ty);
125+
$self.registers.write($dest, $e);
126+
}};
127+
($self:expr, $dest:expr, $lhs:ident: $tyl:ident, $rhs:ident: $tyr:ident, $e:expr) => {{
128+
rx!($self, $lhs: $tyl, $rhs: $tyr);
126129
$self.registers.write($dest, $e);
127130
}};
128-
($self:expr, $($src:ident),+) => {
129-
$(let $src = match $src {
130-
MaybeImm::Reg(src) => $self.registers.get(src),
131-
MaybeImm::Rec(_) => todo!(),
132-
MaybeImm::Imm(src) => &Value::Int(src.into()),
133-
MaybeImm::ImmCnt(src) => &$self.consts.0.get_index(src as _).unwrap().clone(),
134-
MaybeImm::ImmUserVar(src) => {
135-
&$self.symbols.lookup_user_scalar(NonLocal(src.into())).clone()
131+
($self:expr, $($src:ident: $ty:ident),+) => {
132+
use $crate::ir::ArgTy;
133+
$(let $src = match $ty {
134+
ArgTy::Reg => $self.registers.get(unsafe { $src.reg }),
135+
ArgTy::Rec => todo!(),
136+
ArgTy::Imm => &Value::Int(unsafe { $src.imm } as _),
137+
ArgTy::Cnt => &$self.consts.0.get_index(unsafe { $src.sym.0 } as _).unwrap().clone(),
138+
ArgTy::UsVal => {
139+
&$self.symbols.lookup_user_scalar(unsafe { $src.sym }).clone()
136140
}
137-
MaybeImm::ImmBuiltinVar(_) => todo!(),
141+
_ => todo!()
138142
};)+
139143
};
140144
($self:expr, $dest:expr, $lhs:ident, $rhs:ident, $e:expr) => {{
@@ -144,92 +148,102 @@ impl Interpreter<'_> {
144148
}
145149
while let Some(&instr) = self.bc.code.get(self.program_counter) {
146150
match instr {
147-
Instruction::Record(_) => todo!(),
148-
Instruction::Negation((dest, src)) => {
149-
rx!(self, dest, src, Value::b2f(!src.to_bool()));
151+
Instruction::Record { dest: _, arg: _, ty: _ } => todo!(),
152+
Instruction::Negation { dest, arg, ty } => {
153+
rx!(self, dest, arg: ty, Value::b2f(!arg.to_bool()));
154+
}
155+
Instruction::ToInt { dest, arg, ty } => {
156+
rx!(self, dest, arg: ty, Value::Float(arg.to_num().trunc()));
157+
}
158+
Instruction::Negative { dest, arg, ty } => {
159+
rx!(self, dest, arg: ty, Value::Float(-arg.to_num()));
160+
}
161+
Instruction::Copy { dest, arg, ty } => rx!(self, dest, arg: ty, arg.clone()),
162+
Instruction::Eq { dest, lhs, rhs, tyl, tyr } => {
163+
rx!(self, dest, lhs: tyl, rhs: tyr, Value::b2f(lhs == rhs));
150164
}
151-
Instruction::ToInt((dest, src)) => {
152-
rx!(self, dest, src, Value::Float(src.to_num().trunc()));
165+
Instruction::NEq { dest, lhs, rhs, tyl, tyr } => {
166+
rx!(self, dest, lhs: tyl, rhs: tyr, Value::b2f(lhs != rhs));
153167
}
154-
Instruction::Negative((dest, src)) => {
155-
rx!(self, dest, src, Value::Float(-src.to_num()));
168+
Instruction::Gt { dest, lhs, rhs, tyl, tyr } => {
169+
rx!(self, dest, lhs: tyl, rhs: tyr, Value::b2f(lhs > rhs));
156170
}
157-
Instruction::Copy((dest, src)) => rx!(self, dest, src, src.clone()),
158-
Instruction::Eq((dest, lhs, rhs)) => {
159-
rx!(self, dest, lhs, rhs, Value::b2f(lhs == rhs));
171+
Instruction::Lt { dest, lhs, rhs, tyl, tyr } => {
172+
rx!(self, dest, lhs: tyl, rhs: tyr, Value::b2f(lhs < rhs));
160173
}
161-
Instruction::NEq((dest, lhs, rhs)) => {
162-
rx!(self, dest, lhs, rhs, Value::b2f(lhs != rhs));
174+
Instruction::LtE { dest, lhs, rhs, tyl, tyr } => {
175+
rx!(self, dest, lhs: tyl, rhs: tyr, Value::b2f(lhs <= rhs));
163176
}
164-
Instruction::Gt((dest, lhs, rhs)) => {
165-
rx!(self, dest, lhs, rhs, Value::b2f(lhs > rhs));
177+
Instruction::GtE { dest, lhs, rhs, tyl, tyr } => {
178+
rx!(self, dest, lhs: tyl, rhs: tyr, Value::b2f(lhs >= rhs));
166179
}
167-
Instruction::Lt((dest, lhs, rhs)) => {
168-
rx!(self, dest, lhs, rhs, Value::b2f(lhs < rhs));
180+
Instruction::And { dest: _, lhs: _, rhs: _, tyr: _, tyl: _ } => todo!(),
181+
Instruction::Or { dest: _, lhs: _, rhs: _, tyr: _, tyl: _ } => todo!(),
182+
Instruction::Matches { dest: _, lhs: _, rhs: _, tyr: _, tyl: _ } => todo!(),
183+
Instruction::MatchesNot { dest: _, lhs: _, rhs: _, tyr: _, tyl: _ } => todo!(),
184+
Instruction::Add { dest, lhs, rhs, tyl, tyr } => {
185+
rx!(self, dest, lhs: tyl, rhs: tyr, lhs + rhs);
169186
}
170-
Instruction::LtE((dest, lhs, rhs)) => {
171-
rx!(self, dest, lhs, rhs, Value::b2f(lhs <= rhs));
187+
Instruction::Subtract { dest, lhs, rhs, tyl, tyr } => {
188+
rx!(self, dest, lhs: tyl, rhs: tyr, lhs - rhs);
172189
}
173-
Instruction::GtE((dest, lhs, rhs)) => {
174-
rx!(self, dest, lhs, rhs, Value::b2f(lhs >= rhs));
190+
Instruction::Multiply { dest, lhs, rhs, tyl, tyr } => {
191+
rx!(self, dest, lhs: tyl, rhs: tyr, lhs * rhs);
175192
}
176-
Instruction::And((_dest, _lhs, _rhs)) => todo!(),
177-
Instruction::Or((_dest, _lhs, _rhs)) => todo!(),
178-
Instruction::Matches((_dest, _lhs, _rhs)) => todo!(),
179-
Instruction::MatchesNot((_dest, _lhs, _rhs)) => todo!(),
180-
Instruction::Add((dest, lhs, rhs)) => rx!(self, dest, lhs, rhs, lhs + rhs),
181-
Instruction::Subtract((dest, lhs, rhs)) => rx!(self, dest, lhs, rhs, lhs - rhs),
182-
Instruction::Multiply((dest, lhs, rhs)) => rx!(self, dest, lhs, rhs, lhs * rhs),
183-
Instruction::Divide((dest, lhs, rhs)) => rx!(self, dest, lhs, rhs, lhs / rhs),
184-
Instruction::Raise((dest, lhs, rhs)) => rx!(self, dest, lhs, rhs, lhs ^ rhs),
185-
Instruction::Modulo((dest, lhs, rhs)) => rx!(self, dest, lhs, rhs, lhs % rhs),
186-
Instruction::Concat((dest, lhs, rhs)) => {
187-
rx!(self, lhs, rhs);
193+
Instruction::Divide { dest, lhs, rhs, tyl, tyr } => {
194+
rx!(self, dest, lhs: tyl, rhs: tyr, lhs / rhs);
195+
}
196+
Instruction::Raise { dest, lhs, rhs, tyl, tyr } => {
197+
rx!(self, dest, lhs: tyl, rhs: tyr, lhs ^ rhs);
198+
}
199+
Instruction::Modulo { dest, lhs, rhs, tyl, tyr } => {
200+
rx!(self, dest, lhs: tyl, rhs: tyr, lhs % rhs);
201+
}
202+
Instruction::Concat { dest, lhs, rhs, tyl, tyr } => {
203+
rx!(self, lhs: tyl, rhs: tyr);
188204
let mut buf =
189205
StdVec::with_capacity(lhs.string_size_hint() + rhs.string_size_hint());
190206
lhs.write_string(&mut buf);
191207
rhs.write_string(&mut buf);
192208
self.registers.write(dest, Value::String(buf.into()));
193209
}
194-
Instruction::LoadUserScalar((dest, src)) => {
195-
let val = self.symbols.lookup_user_scalar(src);
196-
self.registers.write(dest, val.clone());
197-
}
198-
Instruction::LoadUserArray((_dest, _start, _end, _src)) => todo!(),
199-
Instruction::LoadUserMDimArray((_dest, _start, _end, _place)) => todo!(),
200-
Instruction::LoadBuiltinScalar((_dest, _src)) => todo!(),
201-
Instruction::LoadBuiltinArray((_dest, _src, _start, _end)) => todo!(),
202-
Instruction::LoadConst((dest, src)) => {
203-
let val = self.consts.0.get_index(src.0 as _).unwrap().clone();
204-
self.registers.write(dest, val);
210+
Instruction::LoadA { dest: _, ty_place: _, start: _, end: _, var: _ } => todo!(),
211+
Instruction::StoreS { dest, ty_place, var, arg, ty } => {
212+
rx!(self, arg: ty);
213+
match ty_place {
214+
ArgTy::UsVal => self.symbols.write_user_val(var, arg.clone()),
215+
ArgTy::IsVal => todo!(),
216+
_ => unreachable!(),
217+
}
218+
self.registers.write(dest, arg.clone());
205219
}
206-
Instruction::StoreUserScalar((dest, imm, src)) => {
207-
rx!(self, imm);
208-
self.symbols.write_user_val(src, imm.clone());
209-
self.registers.write(dest, imm.clone());
220+
Instruction::StoreR { dest: _, src: _, arg: _, ty: _, tys: _ } => {
221+
todo!()
210222
}
211-
Instruction::StoreUserArray((_dest, _src, _start, _end)) => todo!(),
212-
Instruction::StoreUserMDimArray((_dest, _start, _end, _place)) => todo!(),
213-
Instruction::StoreRecord(_) => todo!(),
214-
Instruction::StoreBuiltinScalar((_dest, _imm, _src)) => todo!(),
215-
Instruction::StoreBuiltinArray((_dest, _src, _start, _end)) => todo!(),
216-
Instruction::IntrinsicCall((_dest, _start, _end, _fun)) => todo!(),
217-
Instruction::OutputCall((start, end, fun, redir)) => {
218-
self.intrinsic_print(start, end, fun, redir);
223+
Instruction::StoreA {
224+
dest: _,
225+
ty_place: _,
226+
start: _,
227+
end: _,
228+
var: _,
229+
arg: _,
230+
} => todo!(),
231+
Instruction::IntrinsicCall { dest: _, start: _, end: _, name: _ } => todo!(),
232+
Instruction::OutputCall { start, end, cmd, redir } => {
233+
self.intrinsic_print(start, end, cmd, redir);
219234
}
220-
Instruction::UserCall((_dest, _start, _end, _fun)) => todo!(),
221-
Instruction::IndirectCall((_dest, _start, _end, _fun)) => todo!(),
222-
Instruction::Jump(Label(label)) => {
235+
Instruction::UserCall { dest: _, start: _, end: _, name: _ } => todo!(),
236+
Instruction::IndirectCall { dest: _, start: _, end: _, name: _, ty: _ } => todo!(),
237+
Instruction::Jump { to: Label(label) } => {
223238
self.program_counter = label as _;
224239
continue;
225240
}
226-
Instruction::Return(_src) => todo!(),
227-
Instruction::Branch((src, Label(true_to), Label(false_to))) => {
228-
rx!(self, src);
229-
if src.to_bool() {
230-
self.program_counter = true_to as _;
241+
Instruction::Return { arg: _, ty: _ } => todo!(),
242+
Instruction::Branch { then_label, else_label, condition } => {
243+
if self.registers.get(condition).to_bool() {
244+
self.program_counter = then_label.0 as _;
231245
} else {
232-
self.program_counter = false_to as _;
246+
self.program_counter = else_label.0 as _;
233247
}
234248
continue;
235249
}

lexer/src/lib.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use thiserror::Error;
2323
pub type Lexer<'a> = logos::Lexer<'a, Token<'a>>;
2424
pub type Result<T, E = LexingError> = std::result::Result<T, E>;
2525

26-
// TODO: check wnat GNU does about potentially reserved `@ident`; add error branch if so.
2726
#[derive(Logos, Debug, PartialEq)]
2827
#[logos(utf8 = false)]
2928
#[logos(skip(r"(?&ignore)"))]
@@ -34,8 +33,10 @@ pub type Result<T, E = LexingError> = std::result::Result<T, E>;
3433
#[logos(subpattern ignore_with_nl = r"(?:(?&ignore)|\n)*")]
3534
#[logos(error(LexingError, callback = |lex| LexingError::unexpected(lex)))]
3635
pub enum Token<'a> {
37-
#[regex("(-128|(-)?(12[0-7]|1[01][0-9]|[1-9]?[0-9]))", parse_i8, priority = 9)]
38-
SmallInt(i8),
36+
#[regex(r"(-)?\d+", parse_num, priority = 9)]
37+
Numeric,
38+
// Not emitted by Logos directly.
39+
Integer(i32),
3940
#[regex(r"(-)?[0-9]+(\.[0-9]*)?([eE][+-]?[0-9]+)?", parse_float, priority = 8)]
4041
#[regex(r"\.[0-9]+([eE][+-]?[0-9]+)?", parse_float)]
4142
Number(f64),
@@ -484,9 +485,12 @@ fn parse_float(lex: &mut Lexer<'_>) -> f64 {
484485
parse_ident(lex, ..).parse().unwrap_or(0.)
485486
}
486487

487-
fn parse_i8(lex: &mut Lexer<'_>) -> i8 {
488-
// SAFETY: The regex matchin ensures it is well-formed and in [-128, 127].
489-
unsafe { parse_ident(lex, ..).parse().unwrap_unchecked() }
488+
fn parse_num<'a>(lex: &mut Lexer<'a>) -> Token<'a> {
489+
if let Ok(num) = parse_ident(lex, ..).parse() {
490+
Token::Integer(num)
491+
} else {
492+
Token::Number(parse_float(lex))
493+
}
490494
}
491495

492496
fn parse_non_posix_keyword<'a>(lex: &mut Lexer<'a>, other: Token<'a>) -> Token<'a> {

lexer/src/tests.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -123,23 +123,23 @@ fn lexer_test_gnu_pattern() {
123123
#[test]
124124
fn lexer_test_nums() {
125125
let arena = Bump::new();
126-
let str = b"1 20. 0. .3 2e4 -3.e2 5e+1 2.1e-3 -129 -128 -0 127 128";
126+
let str = b"1 20. 0. .3 2e4 -3.e2 5e+1 2.1e-3 -2147483649 -128 -0 127 2147483648";
127127
assert_eq!(
128128
&lex(str, &arena, false, false),
129129
&[
130-
Token::SmallInt(1),
130+
Token::Integer(1),
131131
Token::Number(20.),
132132
Token::Number(0.),
133133
Token::Number(0.3),
134134
Token::Number(2e4),
135135
Token::Number(-3e2),
136136
Token::Number(5e1),
137137
Token::Number(2.1e-3),
138-
Token::Number(-129.),
139-
Token::SmallInt(-128),
140-
Token::SmallInt(0),
141-
Token::SmallInt(127),
142-
Token::Number(128.)
138+
Token::Number(-2_147_483_649.),
139+
Token::Integer(-128),
140+
Token::Integer(0),
141+
Token::Integer(127),
142+
Token::Number(2_147_483_648.)
143143
]
144144
);
145145
}
@@ -165,12 +165,12 @@ fn lexer_test_ident_rules_non_posix() {
165165
assert_eq!(
166166
&lex(b"1a::a a::1a _a", &arena, false, false),
167167
&[
168-
Token::SmallInt(1),
168+
Token::Integer(1),
169169
Token::Identifier(Identifier { namespace: Some("a"), literal: "a" }),
170170
Token::Identifier(Identifier { namespace: None, literal: "a" }),
171171
Token::Colon,
172172
Token::Colon,
173-
Token::SmallInt(1),
173+
Token::Integer(1),
174174
Token::Identifier(Identifier { namespace: None, literal: "a" }),
175175
Token::Identifier(Identifier { namespace: None, literal: "_a" })
176176
]
@@ -205,7 +205,7 @@ fn lexer_test_general_tokens() {
205205
Token::Print,
206206
Token::Identifier(Identifier { namespace: None, literal: "a" }),
207207
Token::Plus,
208-
Token::SmallInt(1),
208+
Token::Integer(1),
209209
Token::ClosedBrace,
210210
Token::Newline,
211211
Token::Regex(b"2\\..*".into()),
@@ -214,7 +214,7 @@ fn lexer_test_general_tokens() {
214214
Token::EndPattern,
215215
Token::OpenBrace,
216216
Token::Record,
217-
Token::SmallInt(1),
217+
Token::Integer(1),
218218
Token::EqualTo,
219219
Token::Identifier(Identifier { namespace: Some("foo"), literal: "bar" }),
220220
Token::ClosedBrace,
@@ -229,12 +229,12 @@ fn lexer_test_regex_ambiguity() {
229229
assert_eq!(
230230
&lex(b"1/=1. a/=1", &arena, false, false),
231231
&[
232-
Token::SmallInt(1),
232+
Token::Integer(1),
233233
Token::SlashAssign,
234234
Token::Number(1.),
235235
Token::Identifier(Identifier { namespace: None, literal: "a" }),
236236
Token::SlashAssign,
237-
Token::SmallInt(1)
237+
Token::Integer(1)
238238
]
239239
);
240240
}

parser/src/ast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ pub struct Rule<'a> {
3535
pub enum Atom<'a> {
3636
Variable(Variable<'a>),
3737
String(Slice<'a>),
38-
SmallInt(i8),
38+
Integer(i32),
3939
Number(f64),
4040
BigInt(),
4141
BigFloat(),

parser/src/lex.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ impl TokenExt for Token<'_> {
221221
fn is_atom(&self) -> bool {
222222
matches!(
223223
self,
224-
Token::Number(_) | Token::SmallInt(_) | Token::String(_) | Token::Regex(_)
224+
Token::Number(_) | Token::Integer(_) | Token::String(_) | Token::Regex(_)
225225
) || self.is_place() && self != &Token::Record
226226
}
227227
fn is_expr_start(&self) -> bool {

parser/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,7 @@ impl<'a> Parser<'a> {
636636
) -> Result<Atom<'a>> {
637637
match token {
638638
Token::Number(n) => Ok(Atom::Number(n)),
639-
Token::SmallInt(n) => Ok(Atom::SmallInt(n)),
639+
Token::Integer(n) => Ok(Atom::Integer(n)),
640640
Token::String(s) => Ok(Atom::String(s)),
641641
Token::Regex(r) => Ok(Atom::Regex(r)),
642642
Token::TypedRegex(r) if typed_regex => Ok(Atom::TypedRegex(r)),

parser/src/sexpr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ impl Debug for Atom<'_> {
292292
Self::Variable(var) => write!(f, "{var:?}"),
293293
Self::String(str) => write!(f, "{str:?}"),
294294
Self::Number(num) => write!(f, "{num}"),
295-
Self::SmallInt(num) => write!(f, "{num}"),
295+
Self::Integer(num) => write!(f, "{num}"),
296296
Self::Regex(rgx) => write!(f, "/{rgx}/"),
297297
Self::TypedRegex(rgx) => write!(f, "@/{rgx}/"),
298298
Self::BigInt() | Self::BigFloat() => unimplemented!(),

0 commit comments

Comments
 (0)