shithub: pprolog

Download patch

ref: 24cdc7adf5611d536403ae625414bb10f3bc4f93
parent: 90664173e5c72d0b31bdfd2c467134b3cfb3623a
author: Peter Mikkelsen <peter@pmikkelsen.com>
date: Tue Jul 20 17:58:46 EDT 2021

Add a new work in progress loader to load all user defined modules

--- a/builtins.c
+++ b/builtins.c
@@ -872,6 +872,9 @@
 	if(error)
 		Throw(realterm);
 
+	if(realterm == nil)
+		Throw(syntaxerror(L"end of stream"));
+
 	Term *singlevars = nil;
 	Term *uniquevars = nil;
 	Term *varsnames = nil;
--- /dev/null
+++ b/loader.pl
@@ -1,0 +1,76 @@
+:- module(loader, []).
+
+load_module_from_file(File) :-
+	write('Loading file: '),
+	write(File),
+	nl,
+	( atom_concat(_, '.pl', File)
+	-> open(File, read, Stream)
+	; atom_concat(File, '.pl', File1),
+	  open(File1, read, Stream)
+	),
+	read_and_handle_terms(Stream, user, _),
+	close(Stream),
+	write('Loaded file: '),
+	write(File),
+	nl.
+
+read_and_handle_terms(Stream, Module0, Module) :-
+	( read_one_term(Stream, Term)
+	-> handle_term(Term, Module0, Module1),
+	   read_and_handle_terms(Stream, Module1, Module)
+	; Module = Module0
+	).
+
+read_one_term(Stream, Term) :-
+	consume_whitespace(Stream),
+	peek_char(Stream, NextCh),
+	NextCh \= end_of_file,
+	read_term(Stream, Term, []).
+
+whitespace(' ').
+whitespace('	').
+whitespace('
+').
+
+consume_whitespace(S) :-
+	peek_char(S, Ch),
+	( whitespace(Ch)
+	-> get_char(S, _), consume_whitespace(S)
+	; true
+	).
+
+handle_term(:- Directive, Module, NewModule) :-
+	!,
+	handle_directive(Directive, Module, NewModule).
+handle_term(Head :- Body, Module, Module) :-
+	!,
+	Module:assertz(Head :- Body).
+handle_term(Head --> Body, Module, Module) :-
+	!,
+	write('DCG RULE: '),
+	write(Head --> Body),
+	nl.
+handle_term(Head, Module, Module) :-
+	Module:assertz(Head).
+
+handle_directive(op(Priority, Specifier, Operator), Module, Module) :-
+	Module:op(Priority, Specifier, Operator).
+handle_directive(include(F), Module, NewModule) :-
+	open(F, read, S),
+	read_and_handle_terms(S, Module, NewModule),
+	close(S).
+handle_directive(ensure_loaded(F), Module, Module) :-
+	ensure_load(F).
+handle_directive(D, Module, Module) :-
+	write('Cannot handle directive: '),
+	write(D),
+	nl.
+
+ensure_loads(_) :- fail.
+
+ensure_load(F) :-
+	( ensure_loads(F)
+	-> true
+	; asserta(ensure_loads(F)), load_module_from_file(F)
+	).
--- a/mkfile
+++ b/mkfile
@@ -23,7 +23,8 @@
 
 PROLOGFILES=\
 	stdlib.pl\
-	repl.pl
+	repl.pl\
+	loader.pl
 
 default:V: all
 
--- a/module.c
+++ b/module.c
@@ -22,6 +22,7 @@
 
 	usermodule = addemptymodule(L"user");
 	parsemodule("/sys/lib/prolog/repl.pl");
+	parsemodule("/sys/lib/prolog/loader.pl");
 }
 
 Module *
--- a/parser.c
+++ b/parser.c
@@ -73,7 +73,7 @@
 	currentmod = usermodule;
 
 	Term *result = prologtext(querymode);
-	if(querymode){
+	if(querymode && result){
 		uvlong id = 1;
 		result = copyterm(result, &id);
 	}
--- a/repl.pl
+++ b/repl.pl
@@ -1,11 +1,12 @@
 :- module(repl, []).
 
 repl([ProgName|Args]) :-
-	write('Welcome to p-prolog version 1'),
+	write('Welcome to p-prolog version 1.'),
 	nl,
 	write('Started with args: '),
 	write(Args),
 	nl,
+	flush_output,
 	handle_args(Args),
 	repl_loop.
 
@@ -12,14 +13,14 @@
 handle_arg('-d') :-
 	set_prolog_flag(debug, on).
 handle_arg(Arg) :-
-	( '$load_module_from_file'(Arg)
-	-> write('Loaded module from file: ')
-	; write('Failed to load module from file: ')
-	),
-	write(Arg), nl.
+	loader:load_module_from_file(Arg).
 
-handle_args([Arg|Rest]) :- handle_arg(Arg), !, handle_args(Rest).
+handle_args([Arg|Rest]) :- catch(handle_arg(Arg), E, handle_arg_error(E)), !, handle_args(Rest).
 handle_args([]).
+
+handle_arg_error(E) :-
+	write('Could not handle arg: '),
+	print_exception(E).
 
 repl_loop :-
 	catch(read_eval_print, E, print_exception(E)),
--- a/stdlib.pl
+++ b/stdlib.pl
@@ -122,7 +122,8 @@
 	current_input(S),
 	stream_property(S, end_of_stream(E)),
 	!,
-	(E = at ; E = past).
+	(E = at ; E = past),
+	!.
 
 at_end_of_stream(S_or_a) :-
 	( atom(S_or_a)
@@ -131,7 +132,8 @@
 	),
 	stream_property(S, end_of_stream(E)),
 	!,
-	(E = at; E = past).
+	(E = at; E = past),
+	!.
 
 % Standard exceptions
 
@@ -677,4 +679,9 @@
 	),
 	is_atom_or_var(Operator),
 	current_ops(Operators),
-	member(op(Priority, Op_specifier, Operator), Operators).
\ No newline at end of file
+	member(op(Priority, Op_specifier, Operator), Operators).
+
+% Loading prolog text
+
+consult(File) :-
+	loader:load_module_from_file(File).
--- a/streams.c
+++ b/streams.c
@@ -323,7 +323,8 @@
 {
 	Stream *s = getstream(t);
 	Rune r = Bgetrune(s->bio);
-	Bungetrune(s->bio);
+	if(r != Beof)
+		Bungetrune(s->bio);
 	return r;
 }
 
@@ -412,11 +413,12 @@
 	/* end_of_stream(E) */
 	if(s->mode == ReadStream){
 		Rune r = Bgetrune(s->bio);
-		Bungetrune(s->bio);
 		if(r == Beof)
 			arg = mkatom(L"at");
-		else
+		else{
+			Bungetrune(s->bio);
 			arg = mkatom(L"not");
+		}
 		data = copyterm(stream, nil);
 		data->next = mkcompound(L"end_of_stream", 1, arg);
 		prop = mkcompound(L"prop", 2, data);