Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 46 additions & 6 deletions awk/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ lazy_static::lazy_static! {
min_args: 1,
max_args: 1,
}),
(Rule::fflush, BuiltinFunctionInfo {
function: BuiltinFunction::FFlush,
min_args: 0,
max_args: 1,
}),
(Rule::system, BuiltinFunctionInfo {
function: BuiltinFunction::System,
min_args: 1,
Expand Down Expand Up @@ -1142,16 +1147,19 @@ impl Compiler {
let stmt = first_child(simple_stmt);
let stmt_line_col = stmt.line_col();
match stmt.as_rule() {
Rule::delete_element => {
Rule::array_delete => {
let mut inner = stmt.into_inner();
let name = inner.next().unwrap();
let get_instruction = self
.get_var(name.as_str(), locals)
.map_err(|msg| pest_error_from_span(name.as_span(), msg))?;
instructions.push(get_instruction, stmt_line_col);
let index = inner.next().unwrap();
self.compile_expr(index, instructions, locals)?;
instructions.push(OpCode::Delete, stmt_line_col);
if let Some(index) = inner.next() {
self.compile_expr(index, instructions, locals)?;
instructions.push(OpCode::DeleteElement, stmt_line_col);
} else {
instructions.push(OpCode::ClearArray, stmt_line_col);
}
}
Rule::expr => {
self.compile_expr(stmt, instructions, locals)?;
Expand Down Expand Up @@ -1451,6 +1459,10 @@ impl Compiler {
Rule::ut_for => self.compile_for(stmt, instructions, locals),
Rule::ut_foreach => self.compile_for_each(stmt, instructions, locals),
Rule::simple_statement => self.compile_simple_statement(stmt, instructions, locals),
Rule::nextfile => {
instructions.push(OpCode::NextFile, stmt.line_col());
Ok(())
}
Rule::next => {
instructions.push(OpCode::Next, stmt.line_col());
Ok(())
Expand Down Expand Up @@ -3022,6 +3034,12 @@ mod test {
assert_eq!(instructions, vec![OpCode::Next]);
}

#[test]
fn test_compile_nextfile() {
let (instructions, _) = compile_stmt("nextfile;");
assert_eq!(instructions, vec![OpCode::NextFile]);
}

#[test]
fn test_compile_exit() {
let (instructions, _) = compile_stmt("exit;");
Expand All @@ -3047,18 +3065,27 @@ mod test {
}

#[test]
fn test_compile_delete() {
fn test_compile_delete_element() {
let (instructions, _) = compile_stmt("delete a[1];");
assert_eq!(
instructions,
vec![
OpCode::GetGlobal(FIRST_GLOBAL_VAR),
OpCode::PushConstant(0),
OpCode::Delete,
OpCode::DeleteElement,
]
);
}

#[test]
fn test_compile_clear_array() {
let (instructions, _) = compile_stmt("delete a");
assert_eq!(
instructions,
vec![OpCode::GetGlobal(FIRST_GLOBAL_VAR), OpCode::ClearArray]
);
}

#[test]
fn test_compile_simple_print() {
let (instructions, constant) = compile_stmt("print 1;");
Expand Down Expand Up @@ -3885,6 +3912,8 @@ mod test {
r#"
BEGIN {
close("file");
fflush("file");
fflush();
system("ls");
}
"#,
Expand All @@ -3899,6 +3928,17 @@ mod test {
},
OpCode::Pop,
OpCode::PushConstant(1),
OpCode::CallBuiltin {
function: BuiltinFunction::FFlush,
argc: 1
},
OpCode::Pop,
OpCode::CallBuiltin {
function: BuiltinFunction::FFlush,
argc: 0
},
OpCode::Pop,
OpCode::PushConstant(2),
OpCode::CallBuiltin {
function: BuiltinFunction::System,
argc: 1,
Expand Down
12 changes: 8 additions & 4 deletions awk/src/grammar.pest
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ builtin_func = _{
| tolower
| toupper
| close
| fflush
| system
}

Expand All @@ -69,6 +70,7 @@ substr = { "substr" }
tolower = { "tolower" }
toupper = { "toupper" }
close = { "close" }
fflush = { "fflush" }
system = { "system" }

keyword = {
Expand Down Expand Up @@ -161,31 +163,33 @@ ut_for = { "for" ~ "(" ~ simple_statement? ~ ";" ~ expr? ~ ";" ~ simple_stat
ut_foreach = { "for" ~ "(" ~ name ~ in_op ~ name ~ ")" ~ opt_newline ~ unterminated_statement }

terminatable_statement = _{
simple_statement
nextfile
| next
| break_stmt
| continue_stmt
| exit_stmt
| return_stmt
| do_while
| simple_statement
}

do_while = { "do" ~ opt_newline ~ terminated_statement ~ "while" ~ "(" ~ expr ~ ")" }
next = { "next" }
nextfile = { "nextfile" }
break_stmt = { "break" }
continue_stmt = { "continue" }

return_stmt = { "return" ~ expr? }
exit_stmt = { "exit" ~ expr? }

simple_statement = {
delete_element
array_delete
| print_stmt
| expr
}

delete_element = {
"delete" ~ name ~ "[" ~ expr ~ "]"
array_delete = {
"delete" ~ name ~ ("[" ~ expr ~ "]")?
}

print_stmt = {
Expand Down
32 changes: 32 additions & 0 deletions awk/src/interpreter/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,22 @@ impl WriteFiles {
Ok(())
}

pub fn flush_file(&mut self, filename: &str) -> bool {
if let Some(file) = self.files.get_mut(filename) {
file.flush().is_ok()
} else {
false
}
}

pub fn flush_all(&mut self) -> bool {
let mut success = true;
for file in self.files.values_mut() {
success = success && file.flush().is_ok();
}
success
}

pub fn close_file(&mut self, filename: &str) {
self.files.remove(filename);
}
Expand Down Expand Up @@ -288,6 +304,22 @@ impl WritePipes {
Ok(())
}

pub fn flush_file(&mut self, filename: &str) -> bool {
if let Some(file) = self.pipes.get(filename) {
unsafe { libc::fflush(*file) == 0 }
} else {
false
}
}

pub fn flush_all(&mut self) -> bool {
let mut success = true;
for file in self.pipes.values() {
success = success && unsafe { libc::fflush(*file) == 0 };
}
success
}

pub fn close_pipe(&mut self, filename: &str) {
if let Some(file) = self.pipes.remove(filename) {
unsafe {
Expand Down
Loading