2016-10-21 20:44:50 +00:00
|
|
|
#! /bin/sh
|
2018-04-29 05:56:52 +00:00
|
|
|
# -*-scheme-*-
|
2018-07-21 05:15:52 +00:00
|
|
|
exec ${GUILE-guile} --no-auto-compile -L $(dirname $0) -C $(dirname $0) -e '(mes-snarf)' -s "$0" "$@"
|
2016-10-21 20:44:50 +00:00
|
|
|
!#
|
|
|
|
|
2018-07-22 12:24:36 +00:00
|
|
|
;;; GNU Mes --- Maxwell Equations of Software
|
2020-05-18 10:10:50 +00:00
|
|
|
;;; Copyright © 2016,2017,2018,2019 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
|
2016-10-21 20:44:50 +00:00
|
|
|
;;;
|
2018-07-22 12:24:36 +00:00
|
|
|
;;; mes-snarf.scm: This file is part of GNU Mes.
|
2016-10-21 20:44:50 +00:00
|
|
|
;;;
|
2018-07-22 12:24:36 +00:00
|
|
|
;;; GNU Mes is free software; you can redistribute it and/or modify it
|
2016-10-21 20:44:50 +00:00
|
|
|
;;; under the terms of the GNU General Public License as published by
|
|
|
|
;;; the Free Software Foundation; either version 3 of the License, or (at
|
|
|
|
;;; your option) any later version.
|
|
|
|
;;;
|
2018-07-22 12:24:36 +00:00
|
|
|
;;; GNU Mes is distributed in the hope that it will be useful, but
|
2016-10-21 20:44:50 +00:00
|
|
|
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
;;; GNU General Public License for more details.
|
|
|
|
;;;
|
|
|
|
;;; You should have received a copy of the GNU General Public License
|
2018-07-22 12:24:36 +00:00
|
|
|
;;; along with GNU Mes. If not, see <http://www.gnu.org/licenses/>.
|
2016-10-21 20:44:50 +00:00
|
|
|
|
|
|
|
(define-module (mes-snarf)
|
|
|
|
#:use-module (srfi srfi-1)
|
2018-04-29 05:56:52 +00:00
|
|
|
#:use-module (srfi srfi-8)
|
|
|
|
#:use-module (srfi srfi-9)
|
2016-10-21 20:44:50 +00:00
|
|
|
#:use-module (srfi srfi-26)
|
|
|
|
#:use-module (ice-9 rdelim)
|
2018-04-29 05:56:52 +00:00
|
|
|
#:export (main))
|
|
|
|
|
|
|
|
(cond-expand
|
|
|
|
(mes
|
|
|
|
(define %scheme "mes"))
|
|
|
|
(guile-2
|
|
|
|
(define %scheme "guile")
|
|
|
|
(define-macro (mes-use-module . rest) #t))
|
|
|
|
(guile
|
|
|
|
(use-modules (ice-9 syncase))
|
|
|
|
(define %scheme "guile")
|
|
|
|
(define-macro (mes-use-module . rest) #t)))
|
|
|
|
|
|
|
|
(mes-use-module (mes guile))
|
|
|
|
(mes-use-module (srfi srfi-1))
|
|
|
|
(mes-use-module (srfi srfi-8))
|
|
|
|
(mes-use-module (srfi srfi-9))
|
|
|
|
(mes-use-module (srfi srfi-26))
|
|
|
|
|
2018-07-21 22:43:39 +00:00
|
|
|
(when (and=> (getenv "V") (lambda (v) (> (string->number v) 1)))
|
|
|
|
(format (current-error-port) "mes-snarf[~a]...\n" %scheme))
|
2018-04-29 05:56:52 +00:00
|
|
|
|
|
|
|
(define (char->char from to char)
|
|
|
|
(if (eq? char from) to char))
|
|
|
|
|
|
|
|
(define (string-replace-char string from to)
|
|
|
|
(string-map (cut char->char from to <>) string))
|
|
|
|
|
|
|
|
(define (string-replace-suffix string from to)
|
|
|
|
(if (string-suffix? from string)
|
|
|
|
(string-replace string to (- (string-length string) (string-length from)))
|
2016-10-21 20:44:50 +00:00
|
|
|
string))
|
|
|
|
|
2018-04-29 05:56:52 +00:00
|
|
|
(define (string-replace-string string from to)
|
|
|
|
(cond ((string-contains string from) => (lambda (i) (string-replace string to i (+ i (string-length from)))))
|
|
|
|
(else string)))
|
|
|
|
|
2017-04-02 15:01:22 +00:00
|
|
|
(define %gcc? #t)
|
2016-10-21 20:44:50 +00:00
|
|
|
|
2018-04-29 16:38:57 +00:00
|
|
|
(define-record-type <file> (make-file name content)
|
2018-04-29 05:56:52 +00:00
|
|
|
file?
|
|
|
|
(name file.name)
|
|
|
|
(content file.content))
|
2016-10-21 20:44:50 +00:00
|
|
|
|
2018-04-29 16:38:57 +00:00
|
|
|
(define-record-type <function> (make-function name formals annotation)
|
2018-04-29 05:56:52 +00:00
|
|
|
function?
|
|
|
|
(name function.name)
|
|
|
|
(formals function.formals)
|
|
|
|
(annotation function.annotation))
|
2016-10-21 20:44:50 +00:00
|
|
|
|
|
|
|
(define (function-scm-name f)
|
2018-04-29 05:56:52 +00:00
|
|
|
(or (assoc-ref (function.annotation f) 'name)
|
2016-12-23 10:31:34 +00:00
|
|
|
(let ((name ((compose
|
2018-04-29 05:56:52 +00:00
|
|
|
identity
|
|
|
|
(cut string-replace-char <> #\_ #\-)
|
|
|
|
(cut string-replace-string <> "_to_" "->")
|
|
|
|
(cut string-replace-suffix <> "_x" "!")
|
|
|
|
(cut string-replace-suffix <> "_x_" "!-")
|
2020-04-20 16:53:28 +00:00
|
|
|
(cut string-replace-suffix <> "_p" "?"))
|
2018-04-29 05:56:52 +00:00
|
|
|
(function.name f))))
|
2016-12-23 10:31:34 +00:00
|
|
|
(if (not (string-suffix? "-" name)) name
|
|
|
|
(string-append "core:" (string-drop-right name 1))))))
|
2016-10-21 20:44:50 +00:00
|
|
|
|
2016-11-21 08:28:34 +00:00
|
|
|
(define %builtin-prefix% "scm_")
|
2016-10-21 20:44:50 +00:00
|
|
|
(define (function-builtin-name f)
|
2018-04-29 05:56:52 +00:00
|
|
|
(string-append %builtin-prefix% (function.name f)))
|
2016-10-21 20:44:50 +00:00
|
|
|
|
2016-11-21 08:28:34 +00:00
|
|
|
(define %cell-prefix% "cell_")
|
|
|
|
(define (function-cell-name f)
|
2018-04-29 05:56:52 +00:00
|
|
|
(string-append %cell-prefix% (function.name f)))
|
2016-10-21 20:44:50 +00:00
|
|
|
|
2016-11-21 08:28:34 +00:00
|
|
|
(define %start 1)
|
|
|
|
(define (symbol->header s i)
|
|
|
|
(string-append
|
2019-02-03 19:59:51 +00:00
|
|
|
(format #f "// CONSTANT ~a ~a\n" s i)
|
|
|
|
(format #f "#define ~a ~a\n" s i)))
|
2016-12-23 09:38:41 +00:00
|
|
|
|
2020-09-27 17:07:00 +00:00
|
|
|
(define (symbol->header s i)
|
|
|
|
(let ((c (string-upcase s)))
|
|
|
|
(string-append
|
|
|
|
(format #f "\n// CONSTANT ~a ~a\n" c i)
|
|
|
|
(format #f "#define ~a ~a\n" c i)
|
|
|
|
(format #f "struct scm *~a; /* ~a */\n" s i))))
|
|
|
|
|
2016-11-21 08:28:34 +00:00
|
|
|
(define (function->header f i)
|
2018-04-29 05:56:52 +00:00
|
|
|
(let* ((arity (or (assoc-ref (function.annotation f) 'arity)
|
|
|
|
(if (string-null? (function.formals f)) 0
|
|
|
|
(length (string-split (function.formals f) #\,)))))
|
2016-11-03 20:28:05 +00:00
|
|
|
(n (if (eq? arity 'n) -1 arity)))
|
2020-09-27 17:07:00 +00:00
|
|
|
(format #f "struct scm *~a (~a);\n" (function.name f) (function.formals f))))
|
2016-11-19 21:31:30 +00:00
|
|
|
|
|
|
|
(define (function->source f i)
|
2019-02-03 19:59:51 +00:00
|
|
|
(let* ((arity (or (assoc-ref (function.annotation f) 'arity)
|
|
|
|
(if (string-null? (function.formals f)) 0
|
|
|
|
(length (string-split (function.formals f) #\,)))))
|
|
|
|
(n (if (eq? arity 'n) -1 arity)))
|
core: Split-out eval-apply.c.
* src/mes.c (check_formals, check_apply, pairlis, set_car_x, set_cdr_x,
set_env_x, call_lambda, make_closure_, make_variable_, macro_get_handle,
get_macro, macro_set_x, push_cc, add_formals, formal_p,
expand_variable_, expand_variable, apply_builtin, eval_apply, apply):
Move to ..
* src/eval-apply.c: New file.
* build-aux/configure-lib.sh (mes_SOURCES): Add it.
* simple.make: Likewise.
* src/eval.c (assert_defined): Likewise.
2020-05-17 18:14:08 +00:00
|
|
|
(format #f " a = init_builtin (builtin_type, ~s, ~a, &~a, a);\n" (function-scm-name f) n (function.name f))))
|
2018-04-29 05:56:52 +00:00
|
|
|
|
|
|
|
(define (disjoin . predicates)
|
|
|
|
(lambda (. arguments)
|
|
|
|
(any (cut apply <> arguments) predicates)))
|
2016-10-21 20:44:50 +00:00
|
|
|
|
|
|
|
(define (snarf-symbols string)
|
2018-04-29 05:56:52 +00:00
|
|
|
(let* ((lines (string-split string #\newline))
|
2020-06-16 13:59:26 +00:00
|
|
|
(symbols (filter (cut string-contains <> " = init_symbol (") lines)))
|
2018-04-29 05:56:52 +00:00
|
|
|
(define (line->symbol line)
|
|
|
|
((compose
|
2020-06-16 13:59:26 +00:00
|
|
|
string-trim-both
|
|
|
|
(lambda (s) (string-take s (string-index s #\=))))
|
2018-04-29 05:56:52 +00:00
|
|
|
line))
|
|
|
|
(map line->symbol symbols)))
|
|
|
|
|
|
|
|
(define (string-split-string string sep)
|
|
|
|
(cond ((string-contains string sep) => (lambda (i) (list (string-take string i) (string-drop string (+ i (string-length sep))))))
|
|
|
|
(else (list string #f))))
|
2016-10-21 20:44:50 +00:00
|
|
|
|
|
|
|
(define (snarf-functions string)
|
2018-04-29 05:56:52 +00:00
|
|
|
(let ((lines (string-split string #\newline)))
|
|
|
|
(filter-map
|
|
|
|
(lambda (line previous)
|
|
|
|
(receive (function rest)
|
|
|
|
(apply values (string-split-string line " "))
|
|
|
|
(and function
|
2020-09-27 17:07:00 +00:00
|
|
|
(or (equal? (string-trim previous) "struct scm*")
|
|
|
|
(equal? (string-trim previous) "struct scm *"))
|
2018-04-29 05:56:52 +00:00
|
|
|
(not (string-null? function))
|
|
|
|
(not (string-prefix? "#" function))
|
|
|
|
(not (string-prefix? "/" function))
|
|
|
|
rest
|
|
|
|
(receive (parameter-list annotation)
|
2020-05-18 10:10:50 +00:00
|
|
|
(apply values (string-split-string rest " /*:"))
|
core: Split-out eval-apply.c.
* src/mes.c (check_formals, check_apply, pairlis, set_car_x, set_cdr_x,
set_env_x, call_lambda, make_closure_, make_variable_, macro_get_handle,
get_macro, macro_set_x, push_cc, add_formals, formal_p,
expand_variable_, expand_variable, apply_builtin, eval_apply, apply):
Move to ..
* src/eval-apply.c: New file.
* build-aux/configure-lib.sh (mes_SOURCES): Add it.
* simple.make: Likewise.
* src/eval.c (assert_defined): Likewise.
2020-05-17 18:14:08 +00:00
|
|
|
(let* ((parameters (string-trim-both parameter-list))
|
|
|
|
(parameters (string-drop parameters 1))
|
2018-04-29 05:56:52 +00:00
|
|
|
(parameters (string-drop-right parameters 1))
|
2020-04-20 16:53:28 +00:00
|
|
|
(annotation (if (string? annotation) (string-trim-both annotation)
|
|
|
|
annotation))
|
|
|
|
(annotation (if (and (string? annotation)
|
|
|
|
(string-suffix? "*/" annotation))
|
|
|
|
(string-drop-right annotation 2)
|
|
|
|
annotation))
|
2018-04-29 05:56:52 +00:00
|
|
|
(formals (if (string-null? parameters) '()
|
|
|
|
(string-split parameters #\,)))
|
|
|
|
(formals (map string-trim formals)))
|
|
|
|
(and parameters
|
2020-09-27 17:07:00 +00:00
|
|
|
(let* ((non-SCM (filter (negate (cut string-prefix? "struct scm" <>)) formals)))
|
2018-04-29 05:56:52 +00:00
|
|
|
(and (null? non-SCM)
|
|
|
|
(let ((annotation (and annotation (with-input-from-string annotation read))))
|
|
|
|
(make-function function parameters annotation))))))))))
|
|
|
|
lines (cons "\n" lines))))
|
2016-10-21 20:44:50 +00:00
|
|
|
|
Move optional type predicates to type.c.
* mes.c (char_p, macro_p, number_p, pair_p, string_p, symbol_p,
vector_p, builtin_p, boolean_p): Move to type.c
* type.c: New file.
* GNUmakefile (mes.o): Depend on type snarf output.
* module/mes/loop-0.mes (cond, map, let, or, and not, evlis-env,
apply-env, eval-expand, uquote, add-unquoters, eval,
expand-macro-env, eval-begin-env, eval-if-env, sexp:define,
env:define, env:macro): Move to mes-0.mes.
* module/mes/mes-0.mes: New file.
* module/mes/type-0.mes: New file.
* scripts/include.mes: If BOOT, also include mes-0.mes. If TYPE0,
also include type-0.mes.
2016-10-22 10:16:19 +00:00
|
|
|
(define (content? f)
|
2018-04-29 05:56:52 +00:00
|
|
|
((compose not string-null? file.content) f))
|
Move optional type predicates to type.c.
* mes.c (char_p, macro_p, number_p, pair_p, string_p, symbol_p,
vector_p, builtin_p, boolean_p): Move to type.c
* type.c: New file.
* GNUmakefile (mes.o): Depend on type snarf output.
* module/mes/loop-0.mes (cond, map, let, or, and not, evlis-env,
apply-env, eval-expand, uquote, add-unquoters, eval,
expand-macro-env, eval-begin-env, eval-if-env, sexp:define,
env:define, env:macro): Move to mes-0.mes.
* module/mes/mes-0.mes: New file.
* module/mes/type-0.mes: New file.
* scripts/include.mes: If BOOT, also include mes-0.mes. If TYPE0,
also include type-0.mes.
2016-10-22 10:16:19 +00:00
|
|
|
|
2016-10-21 20:44:50 +00:00
|
|
|
(define (internal? f)
|
2018-04-29 05:56:52 +00:00
|
|
|
((compose (cut assoc-ref <> 'internal) function.annotation) f))
|
2016-10-21 20:44:50 +00:00
|
|
|
|
|
|
|
(define (no-environment? f)
|
2018-04-29 05:56:52 +00:00
|
|
|
((compose (cut assoc-ref <> 'no-environment) function.annotation) f))
|
2016-10-21 20:44:50 +00:00
|
|
|
|
|
|
|
(define (generate-includes file-name)
|
2018-07-25 06:14:13 +00:00
|
|
|
(let* ((srcdest (or (getenv "srcdest") ""))
|
|
|
|
(string (with-input-from-file (string-append srcdest file-name) read-string))
|
2016-10-21 20:44:50 +00:00
|
|
|
(functions (snarf-functions string))
|
2018-04-29 05:56:52 +00:00
|
|
|
(functions (delete-duplicates functions (lambda (a b) (equal? (function.name a) (function.name b)))))
|
2016-10-21 20:44:50 +00:00
|
|
|
(functions (filter (negate internal?) functions))
|
|
|
|
(symbols (snarf-symbols string))
|
|
|
|
(base-name (basename file-name ".c"))
|
2018-07-25 06:14:13 +00:00
|
|
|
(dir (string-append (dirname file-name)))
|
2017-04-12 19:27:59 +00:00
|
|
|
(base-name (string-append dir "/" base-name))
|
|
|
|
(base-name (if %gcc? base-name
|
|
|
|
(string-append base-name ".mes")))
|
2018-04-29 05:56:52 +00:00
|
|
|
(header (make-file
|
|
|
|
(string-append base-name ".h")
|
|
|
|
(string-join (map function->header functions (iota (length functions) (+ %start (length symbols)))) "")))
|
|
|
|
(source (make-file
|
|
|
|
(string-append base-name ".i")
|
2018-07-21 05:15:52 +00:00
|
|
|
(string-join (map function->source (filter (negate no-environment?) functions) (iota (length functions) (+ (length symbols) %start))) "")))
|
2018-04-29 05:56:52 +00:00
|
|
|
(symbols.h (make-file
|
|
|
|
(string-append base-name ".symbols.h")
|
2019-02-03 19:59:51 +00:00
|
|
|
(string-join (map symbol->header symbols (iota (length symbols) %start)) ""))))
|
|
|
|
(list header source symbols.h)))
|
2016-10-21 20:44:50 +00:00
|
|
|
|
|
|
|
(define (file-write file)
|
2018-07-21 22:43:39 +00:00
|
|
|
(system* "mkdir" "-p" (dirname (file.name file)))
|
2018-04-29 05:56:52 +00:00
|
|
|
(with-output-to-file (file.name file) (lambda () (display (file.content file)))))
|
2016-10-21 20:44:50 +00:00
|
|
|
|
|
|
|
(define (main args)
|
2019-02-03 19:59:51 +00:00
|
|
|
(let* ((files (cdr args))
|
2018-04-29 05:56:52 +00:00
|
|
|
(files (append-map generate-includes files)))
|
2019-02-03 19:59:51 +00:00
|
|
|
(for-each file-write (filter content? files))))
|