On Tuesday, September 3, 2013 5:46:01 AM UTC-7, Philipp Kraus wrote:
> On 2013-08-31 00:55:10 +0000,
graham...@gmail.com said:
>
>
>
> > Can you run LISP on your system?
>
> >
>
> > Then just code UNIFY() in LISP (about 30 lines of code).
>
>
>
> Please read my first posting. I need a DLL structure with a C or C++
>
> interface. I don't run a shell script or anything else.
>
You can easily get a LISP interpreter in C.
And PROLOG is often just a LISP interpreter + 30 lines of LISP
which I gave you.
>
>
> > Or modify the source code of VTProlog or some other small interpreter.
>
> >
>
> > It doesn't get simpler than TurboPascal 3.0.
>
>
>
> Equal argumentation here. I have a system that is written in C++, so I
>
> can not call a stand-alone programm and
>
> TurboPascal binaries can not be called from C++ / C with a DLL call,
>
> because binaries are not compatible.
>
> TurboPascal is also out-of-date and my system must run on Linux, OSX
>
> and Windows (XP, Vista, 7, 8), so
>
> TurboPascal does not work on these systems.
Right but C is based on Pascal.
You'd have to convert the source code into C, this is a linked
lists implementation.
Both the LISP solution and the LL solution are very slow.
{.PW132}
{.IN+}
{.HE VTPROLOG.PAS Page #}
{$V-,R+,B- }
PROGRAM very_tiny_prolog ;
(* Copyright 1986 - MicroExpert Systems
Box 430 R.D. 2
Nassau, NY 12123 *)
(* Revisions - 1.1 Nov. 1986 - Edinburgh list syntax added *)
(* VTPROLOG implements the data base searching and pattern matching of
PROLOG. It is described in "PROLOG from the Bottom Up" in issues
1 and 2 of AI Expert.
This program has been tested using Turbo ver 3.01A on an IBM PC. It has
been run under both DOS 2.1 and Concurrent 4.1 .
We would be pleased to hear your comments, good or bad, or any applications
and modifications of the program. Contact us at:
AI Expert
Miller Freeman Publications
500 Howard St.
San Francisco, CA 94105
Bill and Bev Thompson *)
CONST
debug = false ;
back_space = ^H ;
tab = ^I ;
eof_mark = ^Z ;
esc = #27 ;
quote_char = #39 ;
left_arrow = #75 ;
end_key = #79 ;
del_line = ^X ;
return = ^M ;
bell = ^G ;
TYPE
counter = 0 .. maxint ;
string80 = string[80] ;
string132 = string[132] ;
string255 = string[255] ;
text_file = text ;
char_set = SET OF char ;
node_type = (cons_node,func,variable,constant,free_node) ;
node_ptr = ^node ;
node = RECORD
in_use : boolean ;
CASE tag : node_type OF
cons_node : (tail_ptr : node_ptr ;
head_ptr : node_ptr) ;
func,
constant,
variable : (string_data : string80) ;
free_node : (next_free : node_ptr ;
block_cnt : counter) ;
END ;
(* node is the basic allocation unit for lists. The fields are used as
follows:
in_use - in_use = false tells the garbage collector that this node
is available for re-use.
tag - which kind of node this is.
cons_node - cons_nodes consist of two pointers,
one to the head (first item)
the other to the rest of the list. They are the "glue" which
holds the list together. The list (A B C) would be stored as
------- -------- --------
| .| . |-----> | .| . |------> | .| . |---> NIL
--|----- --|------ --|-----
| | |
V V V
A B C
The boxes are the cons nodes, the first part of the box
holds the head pointer, then second contains the tail.
constant - holds string values, we don't actually use the entire 80
characters in most cases.
variable - also conatins a string value, these nodes will be treated as
PROLOG variables rather than constants.
free_node - the garbage collector gathers all unused nodes and puts
them on a free list. It also compacts the free space into
contiguous blocks. next_free points to the next free block.
block_cnt contains a count of the number of contiguous 8 byte
free blocks which follow this one. *)
VAR
line,saved_line : string132 ;
token : string80 ;
source_file : text_file ;
error_flag,in_comment : boolean ;
delim_set,text_chars : char_set ;
data_base,initial_heap,free,saved_list : node_ptr ;
total_free : real ;
(* The important globals are:
source_file - text file containing PROLOG statements.
line - line buffer for reading in the text file
saved_list - list of all items that absolutely must be saved if garbage
collection occurs. Usually has at least the data_base and
the currents query attached to it.
initial_heap - the value of the heap pointer at the start of the program.
used by the garbage collector
free - the list of free nodes.
total_free - total number of free blocks on the free list.
data_base - a pointer to the start of the data base. It points to a
node pointing to the first sentence in the data base. Nodes
pointing to sentences are linked together to form the data
base.
delim_set - set of characters which delimit tokens. *)
(* ----------------------------------------------------------------------
Utility Routines
---------------------------------------------------------------------- *)
PROCEDURE noise ;
(* Make a noise on the terminal - used for warnings. *)
BEGIN
write(bell) ;
END ; (* noise *)
FUNCTION open(VAR f : text_file ; f_name : string80) : boolean ;
(* open a file - returns true if the file exists and was opened properly
f - file pointer
f_name - external name of the file *)
BEGIN
assign(f,f_name) ;
(*$I- *)
reset(f) ;
(*$I+ *)
open := (ioresult = 0) ;
END ; (* open *)
FUNCTION is_console(VAR f : text_file) : boolean ;
(* return true if f is open on the system console
for details of fibs and fib_ptrs see the Turbo Pascal ver 3.0 reference
manual chapter 20. This should work under CP/M-86 or 80, but we haven't
tried it. *)
TYPE
fib = ARRAY [0 .. 75] OF byte ;
VAR
fib_ptr : ^fib ;
dev_type : byte ;
BEGIN
fib_ptr := addr(f) ;
dev_type := fib_ptr^[2] AND $07 ;
is_console := (dev_type = 1) OR (dev_type = 2) ;
END ; (* is_console *)
PROCEDURE strip_leading_blanks(VAR s : string80) ;
BEGIN
IF length(s) > 0
THEN
IF (s[1] = ' ') OR (s[1] = tab)
THEN
BEGIN
delete(s,1,1) ;
strip_leading_blanks(s) ;
END ;
END ; (* strip_leading_blanks *)
PROCEDURE strip_trailing_blanks(VAR s : string80) ;
BEGIN
IF length(s) > 0
THEN
IF (s[length(s)] = ' ') OR (s[length(s)] = tab)
THEN
BEGIN
delete(s,length(s),1) ;
strip_trailing_blanks(s) ;
END ;
END ; (* strip_trailing_blanks *)
FUNCTION toupper(s : string80) : string80 ;
(* returns s converted to upper case *)
VAR
i : byte ;
BEGIN
IF length(s) > 0
THEN
FOR i := 1 TO length(s) DO
s[i] := upcase(s[i]) ;
toupper := s ;
END ; (* toupper *)
FUNCTION is_number(s : string80) : boolean ;
(* checks to see if s contains a legitimate numerical string.
It ignores leading and trailing blanks *)
VAR
num : real ;
code : integer ;
BEGIN
strip_trailing_blanks(s) ;
strip_leading_blanks(s) ;
IF s <> ''
THEN val(s,num,code)
ELSE code := -1 ;
is_number := (code = 0) ;
END ; (* is_number *)
FUNCTION cardinal(i : integer) : real ;
VAR
r : real ;
BEGIN
r := i ;
IF r < 0
THEN r := r + 65536.0 ;
cardinal := r ;
END ; (* cardinal *)
FUNCTION head(list : node_ptr) : node_ptr ;
(* returns a pointer to the first item in the list.
If the list is empty, it returns NIL. *)
BEGIN
IF list = NIL
THEN head := NIL
ELSE head := list^.head_ptr ;
END ; (* head *)
FUNCTION tail(list : node_ptr) : node_ptr ;
(* returns a pointer to a list starting at the second item in the list.
Note - tail( (a b c) ) points to the list (b c), but
tail( ((a b) c d) ) points to the list (c d) . *)
BEGIN
IF list = NIL
THEN tail := NIL
ELSE
CASE list^.tag OF
cons_node : tail := list^.tail_ptr ;
free_node : tail := list^.next_free ;
ELSE tail := NIL ;
END ;
END ; (* tail *)
Just change BEGIN and END to { and }
C!
Herc
--
www.phpPROLOG.com