SWIPL Zwapel 0.0.1
paule32
Loading...
Searching...
No Matches
prolog.cc
1// --------------------------------------------------------------------------------
2// MIT License
3//
4// Copyright (c) 2023 Jens Kallup
5//
6// Permission is hereby granted, free of charge, to any person obtaining a copy
7// of this software and associated documentation files (the "Software"), to deal
8// in the Software without restriction, including without limitation the rights
9// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10// copies of the Software, and to permit persons to whom the Software is
11// furnished to do so, subject to the following conditions:
12//
13// The above copyright notice and this permission notice shall be included in all
14// copies or substantial portions of the Software.
15//
16// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22// SOFTWARE.
23//
24//! \mainpage Zwapel Project
25//!
26//! This is the Programer's Documentation for the Zwapel Project.<br>
27//! Zwapel is a SWIPL Clone, which you can download <a href="">here</a>.
28//!
29//! ### Namespace
30//!
31//! - \ref zwapel - zwapel namespace provides support for X86/X64 remote
32//! assembly, to speed up the free Prolog System SWIPL.<br>
33//! SWIPL can download from this <a href="https://www.swi-prolog.org/">link</a>.
34//!
35//! SWI-Prolog offers a comprehensive free Prolog environment.
36//! Since its start in 1987, SWI-Prolog development has been driven by the needs<br>
37//! of real world applications. SWI-Prolog is widely used in research and education
38//! as well as commercial applications. Join over a million users <br>
39//! who have downloaded SWI-Prolog.
40//!
41//! ### Legal
42//!
43//! - zwapel is distributed under the MIT license. Some of the used libraries
44//! and extension packages have different license conditions. <br>
45//! The licenses applicable to a running configuration can be examined by
46//! running license/0. See license for details.
47// --------------------------------------------------------------------------------
48
49// ---------------------------------------------------------------------
50// remote assembly headers ...
51// ---------------------------------------------------------------------
52# include <asmjit/core.h>
53# include <asmjit/x86.h>
54
55// ---------------------------------------------------------------------
56// standard c header
57// ---------------------------------------------------------------------
58# include <stdio.h>
59# include <stdlib.h>
60# include <strings.h>
61# include <ctype.h>
62# include <wchar.h>
63# include <limits.h>
64# include <unistd.h>
65# include <getopt.h>
66# include <limits.h>
67# include <sys/types.h>
68# include <sys/stat.h>
69
70// ---------------------------------------------------------------------
71// c++ header
72// ---------------------------------------------------------------------
73# include <iostream>
74# include <string>
75# include <sstream>
76# include <fstream>
77# include <istream>
78# include <codecvt>
79# include <exception>
80# include <vector>
81# include <algorithm>
82# include <iterator>
83# include <csignal>
84# include <type_traits>
85# include <typeinfo>
86
87// ---------------------------------------------------------------------
88// namespace placeholder.
89// ---------------------------------------------------------------------
90using namespace asmjit;
91using namespace x86;
92using namespace std;
93
94// ---------------------------------------------------------------------
95// const, variables.
96// ---------------------------------------------------------------------
97namespace prolog {
98
99#define STDCOUT std::cout
100
101const int CVT_NONE = 0;
102const int CVT_ASM = 1;
103const int CVT_PASCAL = 2; // default ?
104
105int convert_mode = 0;
106
107// ---------------------------------------------------------------------
108//! This is a helper class for the zwapel Prolog classes.
109//!
110//! The class contains misc. help functions that will be use multiple
111//! times in the source code.<br>
112//! It is not the main class, so they can be a little bit twisted till
113//! the end product class system will be reached a profesional stage.
114// ---------------------------------------------------------------------
116public:
117 //-- FUNCTION DEFINITIONS ---------------------------------
118
119 /*! \fn int PL_helper::PL_success()
120 * \brief Prolog member function, that return TRUE on success rule.
121 */
122
123 /*! \fn int PL_helper::PL_fail()
124 * \brief Prolog member function, that return FALSE on fail rule.
125 */
126 int PL_success() { return 0; }
127 int PL_fail () { return 1; }
128};
129
130// ---------------------------------------------------------------------
131// This application provides support for multiple locales. As such, you
132// have to specified, which charset do you would like to use.
133// charset UTF-8 use multibyte character settings, where the rest is
134// reserved for ANSI style characters.
135// ---------------------------------------------------------------------
136template <typename T1>
137class PL_Exception : public std::exception
138{
139 T1 message;
140
141public:
142 PL_Exception(T1 msg): message(msg){}
143 PL_Exception() : message("Prolog Exception."){}
144 const char* what()
145 const throw() {
146 return message.c_str();
147 }
148};
149
150template <typename T1>
151struct PL_stream {
152 static_assert(sizeof(T1) && false,
153 "T1 must be either std::string or std::wstring");
154 T1 readFile(const T1) { }
155};
156
157// -----------------------------------------------------------------------
158// our encoder class for multiple locales (character set's) ...
159// -----------------------------------------------------------------------
160template <typename T1>
162{
163 std::basic_ifstream< T1 > ifile;
164 std::basic_ofstream< T1 > ofile;
165
166 uint8_t PL_size;
167 uint16_t PL_buffer;
168
169 T1 PL_lookaheadChar; // parsed char
170 ::std::basic_string < T1 > PL_ident;
171 ::std::basic_stringstream < T1 > PL_source;
172
173 using PosType = typename std::conditional< std::is_same< T1, char>::value,
174 uint32_t, uint64_t >::type;
175
176pzblic:
177 PosType PL_lookaheadPosition;
178 PosType PL_nestedComment;
179 PosType PL_lineno;
180 PosType PL_size;
181
182public:
183 //-- CONSTRUCTORS DEFINITIONS -----------------------------
184 PL_Encoder(std::basic_string< T1 >&) {
185 }
186 PL_Encoder(std::basic_string< T1 >) {
187 }
188 PL_Encoder(char&) {
189 }
190 PL_Encoder(char) {
191 }
192 PL_Encoder() {
193 }
194
195 //-- FUNCTION DEFINITIONS ---------------------------------
196 uint16_t getch()
197 {
198 char buffer[4];
199 PL_lookaheadPosition = PL_lookaheadPosition + 1;
200 if (PL_lookaheadPosition >= PL_size) return 0x0;
201 if (PL_size < 1) {
202 PL_Exception<std::string> ex("data get underflow.");
203 throw ex;
204 } else
205 if (PL_size < 2) {
206 PL_source.get(buffer,1);
207 PL_buffer = ((uint16_t) buffer[0] << 8) | 0x00;
208 } else
209 if (PL_size < 3) {
210 PL_source.get(buffer,2);
211 PL_buffer = ((uint16_t) buffer[0] << 8) | buffer[1];
212 }
213 return PL_buffer;
214 }
215
216 std::basic_string< T1 >
217 PL_parseFile(const std::basic_string< T1 > &filename, PL_Encoder &in)
218 {
219 if (std::is_same< T1, char >::value) { ifile.open(filename); } else
220 if (std::is_same< T1, std::string>::value) { ifile.open(filename); }
221 else {
222 ifile.imbue(std::locale(std::locale(),
223 new std::codecvt_utf8< wchar_t >));
224 PL_size = sizeof(wchar_t);
225 }
226
227 if (ifile.is_open()) {
228 PL_source << ifile.rdbuf();
229 PL_size = sizeof( char );
230
231 // get size
232 PL_source.seekg(0, std::ios::end);
233 PL_size = PL_source.tellg();
234 PL_source.seekg(0, std::ios::beg);
235
236 return PL_source.str();
237 } else {
238 PL_Exception< std::string > ex("input file read error");
239 throw ex;
240 }
241
242 in.PL_ident.clear();
243
244 while (1) {
245 label_start:
246 if (!(in.PL_lookaheadChar = in.getch()))
247 break;
248
249 if (
250 (in.PL_lookaheadChar == ' ' ) ||
251 (in.PL_lookaheadChar == '\t')) {
252 continue;
253 }
254
255 if (in.PL_lookaheadChar == '\n') {
256 in.PL_lineno =
257 in.PL_lineno + 1;
258 continue;
259 }
260
261 if (in.PL_lookaheadChar == '/')
262 {
263 if (!(in.PL_lookaheadChar = in.getch())) {
264 PL_Exception<std::string> ex("not yet implemented.");
265 throw ex;
266 }
267
268 if (in.PL_lookaheadChar == '*')
269 {
270 in.PL_nestedComment =
271 in.PL_nestedComment + 1;
272
273 while (1) {
274 label_comment2:
275 if (!(in.PL_lookaheadChar = in.getch())) {
276 PL_Exception<std::string> ex("unterminated comment");
277 throw ex;
278 }
279
280 if (in.PL_lookaheadChar == '\n') {
281 in.PL_lineno =
282 in.PL_lineno + 1;
283 continue;
284 }
285
286 if (in.PL_lookaheadChar == '/') {
287 if (!(in.PL_lookaheadChar = in.getch())) {
288 PL_Exception<std::string> ex("unterminated comment");
289 throw ex;
290 }
291
292 if (in.PL_lookaheadChar == '*') {
293 in.PL_nestedComment =
294 in.PL_nestedComment + 1;
295 continue;
296 }
297 }
298
299 if (in.PL_lookaheadChar == '*') {
300 if (!(in.PL_lookaheadChar = in.getch())) {
301 PL_Exception<std::string> ex("unterminated comment");
302 throw ex;
303 }
304
305 if (in.PL_lookaheadChar == '/') {
306 in.PL_nestedComment =
307 in.PL_nestedComment - 1; if (
308 in.PL_nestedComment < 1)
309 break;
310 }
311 }
312 }
313 } else {
314 // todo
315 PL_Exception<std::string> ex("not yets implemented.");
316 throw ex;
317 }
318 }
319
320 // one line comment
321 if (in.PL_lookaheadChar == '%') {
322 label_comment:
323 while (1) {
324 if (!(in.PL_lookaheadChar = in.getch()))
325 break;
326
327 if (in.PL_lookaheadChar == '\n') {
328 in.PL_lineno =
329 in.PL_lineno + 1;
330 break;
331 }
332 }
333
334 if (in.PL_lookaheadPosition >= in.PL_size)
335 break;
336 continue;
337 }
338
339 if (
340 (in.PL_lookaheadChar >= 'a' && in.PL_lookaheadChar <= 'z') ||
341 (in.PL_lookaheadChar >= 'A' && in.PL_lookaheadChar <= 'A') ||
342 (in.PL_lookaheadChar == '_'))
343 {
344 label_ident:
345 in.PL_ident += in.PL_lookaheadChar;
346
347 while (
348 in.PL_lookaheadPosition !=
349 in.PL_size)
350 {
351 in.PL_lookaheadChar = in.getch();
352 if (in.PL_lookaheadChar == '\n') {
353 STDCOUT <<
354 in.PL_ident << std::endl;
355 in.PL_ident.clear();
356 in.PL_lineno =
357 in.PL_lineno + 1;
358 break;
359 }
360
361 if (
362 (in.PL_lookaheadChar >= 'a' && in.PL_lookaheadChar <= 'z') ||
363 (in.PL_lookaheadChar >= 'A' && in.PL_lookaheadChar <= 'A') ||
364 (in.PL_lookaheadChar >= '0' && in.PL_lookaheadChar <= '9') ||
365 (in.PL_lookaheadChar == '_')) {
366 if (in.PL_nestedComment < 1) {
367 goto label_ident;
368 }
369 }
370 else {
371 STDCOUT <<
372 in.PL_ident << std::endl;
373 in.PL_ident.clear();
374 break;
375 }
376 }
377 }
378 }
379 }
380};
381
382void
383on_setMode(std::string mode) {
384 if (mode == std::string("pascal")) convert_mode = CVT_PASCAL; else
385 if (mode == std::string("asm" )) convert_mode = CVT_ASM;
386}
387
388} // namespace: prolog
389
390// ---------------------------------------------------------------------
391// test case entry point ...
392// ---------------------------------------------------------------------
393using namespace prolog;
394int
395main(int argc, char** argv)
396{
397 #if __CHARSET_UTF8__
398 PL_Encoder<wchar_t> input ;
399 PL_Encoder<wchar_t> output;
400 #else
401 PL_Encoder<char > input ;
402 PL_Encoder<char > output;
403 #endif
404
405 //-- INITIAL STUFF ----------------------------------------
406 input.PL_lookaheadPosition = -1;
407 input.PL_lineno = 1;
408 input.PL_nestedComment = 0;
409
410 try {
411 if (argc < 3) {
412 PL_Exception<std::string> ex("too few arguments.");
413 throw ex;
414 }
415 if (std::string(argv[1]).size() < 1) {
416 PL_Exception<std::string> ex("error: can not open input file.");
417 throw ex;
418 }
419 if (std::string(argv[2]).size() < 1) {
420 PL_Exception<std::string> ex("error: can not open output file.");
421 throw ex;
422 }
423
424 input.PL_parseFile( std::string( argv[1] ), input );
425
426 STDCOUT
427 << std::endl
428 << "Compiled: OK" << std::endl
429 << "Lines : " << input.PL_lineno << std::endl;
430 }
432 {
433 STDCOUT
434 << "error : " << input.PL_lineno
435 << std::endl
436 << "reason: " << e.what()
437 << std::endl;
438
439 return 1;
440 } return 0;
441}
This is a helper class for the zwapel Prolog classes.
Definition: prolog.cc:115
int PL_success()
Prolog member function, that return TRUE on success rule.
Definition: prolog.cc:126
int PL_fail()
Prolog member function, that return FALSE on fail rule.
Definition: prolog.cc:127