From 1ea6ae9fd90ff0067e47a3e1190cbe112c9e5700 Mon Sep 17 00:00:00 2001 From: notoria Date: Sat, 18 Apr 2020 11:49:28 +0200 Subject: [PATCH 1/7] Added predicate for reading a single character --- src/prolog/clause_types.rs | 3 +++ src/prolog/lib/builtins.pl | 11 +++++++++-- src/prolog/machine/system_calls.rs | 25 +++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/prolog/clause_types.rs b/src/prolog/clause_types.rs index 7100855e..37c8f612 100644 --- a/src/prolog/clause_types.rs +++ b/src/prolog/clause_types.rs @@ -178,6 +178,7 @@ pub enum SystemClauseType { FetchGlobalVar, FetchGlobalVarWithOffset, GetChar, + GetSingleChar, ResetAttrVarState, TruncateIfNoLiftedHeapGrowthDiff, TruncateIfNoLiftedHeapGrowth, @@ -309,6 +310,7 @@ impl SystemClauseType { clause_name!("$fetch_global_var_with_offset") } &SystemClauseType::GetChar => clause_name!("$get_char"), + &SystemClauseType::GetSingleChar => clause_name!("$get_single_char"), &SystemClauseType::ResetAttrVarState => clause_name!("$reset_attr_var_state"), &SystemClauseType::TruncateIfNoLiftedHeapGrowth => { clause_name!("$truncate_if_no_lh_growth") @@ -455,6 +457,7 @@ impl SystemClauseType { ("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar), ("$fetch_global_var_with_offset", 3) => Some(SystemClauseType::FetchGlobalVarWithOffset), ("$get_char", 1) => Some(SystemClauseType::GetChar), + ("$get_single_char", 1) => Some(SystemClauseType::GetSingleChar), ("$points_to_cont_reset_marker", 1) => { Some(SystemClauseType::PointsToContinuationResetMarker) } diff --git a/src/prolog/lib/builtins.pl b/src/prolog/lib/builtins.pl index 17235d3b..15c81403 100644 --- a/src/prolog/lib/builtins.pl +++ b/src/prolog/lib/builtins.pl @@ -47,8 +47,8 @@ user:term_expansion((:- op(Pred, Spec, [Op | OtherOps])), OpResults) :- current_input/1, current_output/1, current_op/3, current_predicate/1, current_prolog_flag/2, expand_goal/2, expand_term/2, fail/0, false/0, - findall/3, findall/4, get_char/1, halt/0, - max_arity/1, number_chars/2, number_codes/2, + findall/3, findall/4, get_char/1, get_single_char/1, + halt/0, max_arity/1, number_chars/2, number_codes/2, once/1, op/3, read_term/2, repeat/0, retract/1, set_prolog_flag/2, set_input/1, set_output/1, setof/3, sub_atom/5, subsumes_term/2, @@ -933,6 +933,13 @@ get_char(C) :- ; throw(error(type_error(in_character, C), get_char/1)) ). +get_single_char(C) :- + ( var(C) -> '$get_single_char'(C) + ; C == end_of_file -> '$get_single_char'(C) + ; atom_length(C, 1) -> '$get_single_char'(C) + ; throw(error(type_error(in_character, C), get_char/1)) + ). + can_be_number(N, PI) :- ( var(N) -> true ; must_be_number(N, PI) diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index cd9cc86f..bd35d6e6 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -67,6 +67,24 @@ pub fn next_keypress() -> ContinueResult { } } +pub fn get_single_char() -> char { + let c; + enable_raw_mode().expect("failed to enable raw mode"); + loop { + if let Ok(Event::Key(KeyEvent { code, .. })) = read() { + match code { + KeyCode::Char(ch) => { + c = ch; + break; + }, + _ => () + } + } + } + disable_raw_mode().expect("failed to disable raw mode"); + c +} + struct BrentAlgState { hare: Addr, tortoise: Addr, @@ -1463,6 +1481,13 @@ impl MachineState { } } } + &SystemClauseType::GetSingleChar => { + let c = get_single_char(); + + let a1 = self[temp_v!(1)]; + + self.unify(Addr::Char(c), a1); + } &SystemClauseType::GetModuleClause => { let module = self[temp_v!(3)]; let head = self[temp_v!(1)]; From 11ea92288d50a3f0a2fb3a90077abf559b1f5783 Mon Sep 17 00:00:00 2001 From: notoria Date: Sat, 18 Apr 2020 12:52:49 +0200 Subject: [PATCH 2/7] Moved get_single_char from builtins.pl to charsio.pl --- src/prolog/lib/builtins.pl | 11 ++--------- src/prolog/lib/charsio.pl | 11 ++++++++++- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/prolog/lib/builtins.pl b/src/prolog/lib/builtins.pl index 15c81403..17235d3b 100644 --- a/src/prolog/lib/builtins.pl +++ b/src/prolog/lib/builtins.pl @@ -47,8 +47,8 @@ user:term_expansion((:- op(Pred, Spec, [Op | OtherOps])), OpResults) :- current_input/1, current_output/1, current_op/3, current_predicate/1, current_prolog_flag/2, expand_goal/2, expand_term/2, fail/0, false/0, - findall/3, findall/4, get_char/1, get_single_char/1, - halt/0, max_arity/1, number_chars/2, number_codes/2, + findall/3, findall/4, get_char/1, halt/0, + max_arity/1, number_chars/2, number_codes/2, once/1, op/3, read_term/2, repeat/0, retract/1, set_prolog_flag/2, set_input/1, set_output/1, setof/3, sub_atom/5, subsumes_term/2, @@ -933,13 +933,6 @@ get_char(C) :- ; throw(error(type_error(in_character, C), get_char/1)) ). -get_single_char(C) :- - ( var(C) -> '$get_single_char'(C) - ; C == end_of_file -> '$get_single_char'(C) - ; atom_length(C, 1) -> '$get_single_char'(C) - ; throw(error(type_error(in_character, C), get_char/1)) - ). - can_be_number(N, PI) :- ( var(N) -> true ; must_be_number(N, PI) diff --git a/src/prolog/lib/charsio.pl b/src/prolog/lib/charsio.pl index 9cf5f325..5fde900c 100644 --- a/src/prolog/lib/charsio.pl +++ b/src/prolog/lib/charsio.pl @@ -1,4 +1,5 @@ -:- module(charsio, [read_term_from_chars/2, +:- module(charsio, [get_single_char/1, + read_term_from_chars/2, write_term_to_chars/3]). :- use_module(library(iso_ext)). @@ -56,6 +57,14 @@ extend_var_list_([V|Vs], N, VarList, NewVarList, VarType) :- ). +get_single_char(C) :- + ( var(C) -> '$get_single_char'(C) + ; C == end_of_file -> '$get_single_char'(C) + ; atom_length(C, 1) -> '$get_single_char'(C) + ; throw(error(type_error(in_character, C), get_char/1)) + ). + + read_term_from_chars(Chars, Term) :- ( var(Chars) -> throw(error(instantiation_error, read_term_from_chars/2)) From 5d064b18e61b4b7a6c2aa61b84fa8110c4429d76 Mon Sep 17 00:00:00 2001 From: notoria Date: Sat, 18 Apr 2020 13:30:52 +0200 Subject: [PATCH 3/7] get_single_char reads Enter as \n --- src/prolog/machine/system_calls.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index bd35d6e6..1b2f48f0 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -77,6 +77,10 @@ pub fn get_single_char() -> char { c = ch; break; }, + KeyCode::Enter => { + c = '\n'; + break; + }, _ => () } } From b35b49f7b3636a786d0f996f4189a36ab6883a3e Mon Sep 17 00:00:00 2001 From: notoria Date: Sat, 18 Apr 2020 13:33:42 +0200 Subject: [PATCH 4/7] get_single_char reads Tab as \t --- src/prolog/machine/system_calls.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index 1b2f48f0..1a783ac9 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -81,6 +81,10 @@ pub fn get_single_char() -> char { c = '\n'; break; }, + KeyCode::Tab => { + c = '\t'; + break; + }, _ => () } } From 99e1a5f11749a519a2ecde8cc9d1ffe9bea925ad Mon Sep 17 00:00:00 2001 From: notoria Date: Sat, 18 Apr 2020 13:54:18 +0200 Subject: [PATCH 5/7] Removed $raw_input_read_char --- src/prolog/clause_types.rs | 3 -- src/prolog/machine/system_calls.rs | 56 ------------------------------ src/prolog/toplevel.pl | 5 +-- 3 files changed, 3 insertions(+), 61 deletions(-) diff --git a/src/prolog/clause_types.rs b/src/prolog/clause_types.rs index 37c8f612..660de341 100644 --- a/src/prolog/clause_types.rs +++ b/src/prolog/clause_types.rs @@ -242,7 +242,6 @@ pub enum SystemClauseType { InstallNewBlock, Maybe, QuotedToken, - RawInputReadChar, ReadTermFromChars, ResetBlock, ReturnFromVerifyAttr, @@ -366,7 +365,6 @@ impl SystemClauseType { &SystemClauseType::QuotedToken => { clause_name!("$quoted_token") } - &SystemClauseType::RawInputReadChar => clause_name!("$raw_input_read_char"), &SystemClauseType::RedoAttrVarBinding => clause_name!("$redo_attr_var_binding"), &SystemClauseType::RemoveCallPolicyCheck => clause_name!("$remove_call_policy_check"), &SystemClauseType::RemoveInferenceCounter => clause_name!("$remove_inference_counter"), @@ -509,7 +507,6 @@ impl SystemClauseType { ("$get_cp", 1) => Some(SystemClauseType::GetCutPoint), ("$install_new_block", 1) => Some(SystemClauseType::InstallNewBlock), ("$quoted_token", 1) => Some(SystemClauseType::QuotedToken), - ("$raw_input_read_char", 1) => Some(SystemClauseType::RawInputReadChar), ("$nextEP", 3) => Some(SystemClauseType::NextEP), ("$read_query_term", 2) => Some(SystemClauseType::ReadQueryTerm), ("$read_term", 2) => Some(SystemClauseType::ReadTerm), diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index 1a783ac9..e2cad96a 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -31,42 +31,6 @@ use std::rc::Rc; use crate::crossterm::event::{read, Event, KeyCode, KeyEvent}; use crate::crossterm::terminal::{enable_raw_mode, disable_raw_mode}; -pub enum ContinueResult { - ContinueQuery, - Conclude, - Help, - PrintWithoutMaxDepth, - PrintWithMaxDepth -} - -pub fn next_keypress() -> ContinueResult { - loop { - match read() { - Ok(Event::Key(KeyEvent { code, .. })) => { - match code { - KeyCode::Char('w') => { - return ContinueResult::PrintWithoutMaxDepth; - } - KeyCode::Char('p') => { - return ContinueResult::PrintWithMaxDepth; - } - KeyCode::Char(' ') | KeyCode::Char(';') | KeyCode::Char('n') => { - return ContinueResult::ContinueQuery; - } - KeyCode::Char('.') => { - return ContinueResult::Conclude; - } - KeyCode::Char('h') => { - return ContinueResult::Help; - } - _ => {} - } - } - _ => {} - } - } -} - pub fn get_single_char() -> char { let c; enable_raw_mode().expect("failed to enable raw mode"); @@ -2913,26 +2877,6 @@ impl MachineState { &SystemClauseType::InstallNewBlock => { self.install_new_block(temp_v!(1)); } - &SystemClauseType::RawInputReadChar => { - let keypress = { - enable_raw_mode().expect("failed to transition into raw mode"); - let result = next_keypress(); - disable_raw_mode().expect("failed to transition out of raw mode"); - - result - }; - - let c = match keypress { - ContinueResult::ContinueQuery => ';', - ContinueResult::Conclude => '.', - ContinueResult::Help => 'h', - ContinueResult::PrintWithoutMaxDepth => 'w', - ContinueResult::PrintWithMaxDepth => 'p', - }; - - let target = self[temp_v!(1)]; - self.unify(Addr::Char(c), target); - } &SystemClauseType::NextEP => { let first_arg = self.store(self.deref(self[temp_v!(1)])); diff --git a/src/prolog/toplevel.pl b/src/prolog/toplevel.pl index 27bf71f5..e7eb3b7a 100644 --- a/src/prolog/toplevel.pl +++ b/src/prolog/toplevel.pl @@ -145,7 +145,7 @@ ). '$read_input'(ThreadedGoals, NewVarList) :- - '$raw_input_read_char'(C), + '$get_single_char'(C), ( C == w -> nl, write(' '), @@ -161,8 +161,9 @@ ; C == h -> '$help_message', '$read_input'(ThreadedGoals, NewVarList) - ; C == '.', + ; C == '.' -> nl, write('; ...'), nl + ; '$read_input'(ThreadedGoals, NewVarList) ). '$help_message' :- From 105e9c8e8887dbbb281454cabca323cb07dbe1b1 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Sat, 18 Apr 2020 14:33:11 +0200 Subject: [PATCH 6/7] use get_single_char/1 --- src/prolog/toplevel.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/prolog/toplevel.pl b/src/prolog/toplevel.pl index e7eb3b7a..dc58c386 100644 --- a/src/prolog/toplevel.pl +++ b/src/prolog/toplevel.pl @@ -145,7 +145,7 @@ ). '$read_input'(ThreadedGoals, NewVarList) :- - '$get_single_char'(C), + get_single_char(C), ( C == w -> nl, write(' '), From 1f7e18f2a9e9893d5a5f2199e1571cbcce80fc82 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Sat, 18 Apr 2020 14:38:03 +0200 Subject: [PATCH 7/7] instead of a type error, use a domain error The preceding use of atom_length/2 already ensures that C has the correct type (i.e., atom). However, its domain may still be wrong, if its length is greater than 1. --- src/prolog/lib/charsio.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/prolog/lib/charsio.pl b/src/prolog/lib/charsio.pl index 5fde900c..29a668fd 100644 --- a/src/prolog/lib/charsio.pl +++ b/src/prolog/lib/charsio.pl @@ -61,7 +61,7 @@ get_single_char(C) :- ( var(C) -> '$get_single_char'(C) ; C == end_of_file -> '$get_single_char'(C) ; atom_length(C, 1) -> '$get_single_char'(C) - ; throw(error(type_error(in_character, C), get_char/1)) + ; throw(error(domain_error(in_character, C), get_char/1)) ).