1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-30 00:40:20 +02:00
guile/module/language/sassy/parse.scm
Andy Wingo 66ff15e2f0 add the sassy x86 assembler
* module/Makefile.am: Add language/sassy.scm. Probably EXTRA_DIST the
  dependant files, too.
* module/language/sassy.scm: New file, the sassy loader. Sassy is
  originally R5RS code that loads a number of files. I've converted that
  toplevel file to be a Guile module that *includes* the subfiles, so
  that it all gets compiled together. It's a pretty bad hack though,
  because what I should be doing is including them relative to the
  sassy.scm source location, but we don't know that at expansion time.
  Something to fix.
  really bad hack in it so that it will compile correctly -- p

* module/language/sassy/: All the sassy files and some changelog
  information. All of these files are LGPLv2.1+, so they can be included
  in Guile.

* test-suite/standalone/sassy/tests/: Add the sassy unit tests.
* test-suite/standalone/Makefile.am:
* test-suite/standalone/test-sassy: Hook the sassy unit tests up to our
  test suite.
2009-08-13 18:48:20 +02:00

282 lines
9.7 KiB
Scheme

; parse.scm - Sassy's top level parser
; Copyright (C) 2005 Jonathan Kraut
; This library is free software; you can redistribute it and/or
; modify it under the terms of the GNU Lesser General Public
; License as published by the Free Software Foundation; either
; version 2.1 of the License, or (at your option) any later version.
; This library is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
; Lesser General Public License for more details.
; You should have received a copy of the GNU Lesser General Public
; License along with this library; if not, write to the Free Software
; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
; Contact:
; Jonathan Kraut
; 4130 43 ST #C2
; Sunnyside, NY 11104
; jak76@columbia.edu
; see file COPYING in the top of Sassy's distribution directory
; module parse
; import macros api text numbers opcodes push-stacks operands intern
; import-syntax meta-lambda
; export all
(define parse-directives
(let ()
(define (process-bits int output)
(if (or (= 16 int) (= 32 int))
(sassy-bits-set! output int)
(error "sassy: bad bits" int)))
(define (process-org text-base output)
(if (and (integer? text-base)
(zero? (sassy-text-size output))
(positive? text-base))
(sassy-text-org-set! output text-base)
(error "sassy: bad org" text-base)))
(define (process-entry entry-label output)
(if (symbol? entry-label)
(begin (sassy-symbol-set! output entry-label '(scope export))
(sassy-entry-point-set! output entry-label))
(error "sassy: bad entry" entry-label)))
(define (process-include include-list output)
(for-each
(lambda (x)
(cond ((string? x) (parse-directives (read-file x) output))
((symbol? x) (parse-directives (eval x
(interaction-environment))
output))
(else (error "sassy: bad include" x))))
include-list))
(define (process-scopes scope-list scope output)
(for-each (lambda (x)
(if (eq? 'import scope)
(sassy-symbol-def-error output x))
(if (symbol? x)
(sassy-symbol-set! output x `(scope ,scope))
(error "sassy: bad scope" scope x)))
scope-list))
(define (align-to count align)
(let ((diff (modulo count align)))
(if (zero? diff)
0
(- align diff))))
(define aligner
(let ((power-of-2 (lambda (x)
(and (integer? x) (positive? x)
(zero? (logand x (- x 1)))
x))))
(meta-lambda
(and 'align power-of-2))))
(define (process-heap heap-list output)
(letrec
((heap-sizer
(meta-lambda
(or (and 'bytes u-dword)
(and 'words u-dword (lambda (units) (* units 2)))
(and 'dwords u-dword (lambda (units) (* units 4)))
(and 'qwords u-dword (lambda (units) (* units 8))))))
(heap-item
(meta-lambda
(or
(and ,@aligner (lambda (align)
(let ((size (sassy-heap-size output)))
(sassy-heap-size-set!
output (+ size (align-to size align)))
(when (> align (sassy-heap-align output))
(sassy-heap-align-set! output align)))))
(and ,@heap-sizer (lambda (sizer)
(sassy-heap-size-set!
output (+ sizer (sassy-heap-size output)))))
(and 'label valid-label __
(lambda (label . rst)
(let ((current-size (sassy-heap-size output)))
(sassy-symbol-def-error output label)
(sassy-symbol-set! output label '(section heap)
`(offset ,current-size) '(size 0))
(for-each heap-item rst)
(sassy-symbol-set! output label
`(size ,(- (sassy-heap-size output)
current-size))))))
(and 'begin (* heap-item))
(else (lambda (h) (error "sassy: bad heap item" h)))))))
(for-each heap-item heap-list)))
(define (process-text text-list output)
(letrec ((text-item
(meta-lambda
(or
(and ,@aligner (lambda (align)
(push-stack-align (sassy-text-stack output)
align #x90
(sassy-text-org output))
(if (> align (sassy-text-align output))
(sassy-text-align-set! output align))))
(and 'label valid-label __
(lambda (label . opcodes-or-prims)
(sassy-symbol-def-error output label)
(sassy-symbol-set!
output label
'(section text)
`(offset ,(+ (sassy-text-org output)
(sassy-text-size output))))
(sassy-symbol-set!
output label
`(size ,(handle-text-block `(begin ,@opcodes-or-prims)
output (t-make))))))
(else (lambda (opcode-or-prim)
(handle-text-block opcode-or-prim output
(t-make))))))))
(for-each text-item text-list)))
(define (sassy-reloc-set! output name section offset type patcher)
(sassy-reloc-list-set!
output (cons (make-sassy-reloc name section offset type patcher)
(sassy-reloc-list output))))
(define (process-data data-list output)
(letrec
((current-byte-size (/ (sassy-bits output) 8))
(char/str/num
(lambda (item size)
(let ((data-stack (sassy-data-stack output)))
(cond ((char? item)
(push-stack-push data-stack (char->integer item))
(push-stack-align data-stack size 0))
((string? item)
(push-stack-push data-stack
(map char->integer (string->list item)))
(push-stack-align data-stack size 0))
((number? item)
(push-stack-push data-stack
(number->byte-list item size)))
(else (lambda (i) (error "sassy: bad data" i)))))))
(handle-data-symbol
(lambda (type target value)
(when (eqv? 'rel type)
(error "no rel relocations in data section right now"
(list 'reloc type target value)))
(when (eqv? '$here target)
(set! target (sassy-data-size output)))
(let* ((offset (sassy-data-size output))
(target-value (cond ((sassy-symbol-exists-env?
output target)
=>
(lambda (x) (sassy-symbol-offset x)))
(else target)))
(a-reloc (make-sassy-reloc
(get-reloc-target target output)
'data offset type #f value current-byte-size))
(patcher (let ((p (push-stack-push->patcher
(sassy-data-stack output)
(number->byte-list value
current-byte-size))))
(lambda (new)
(p (number->byte-list new current-byte-size))
(sassy-reloc-value-set! a-reloc new)))))
(sassy-reloc-patcher-set! a-reloc patcher)
(sassy-reloc-list-set! output
(cons a-reloc (sassy-reloc-list output)))
(if (number? target-value)
(patcher (+ target-value value))
(sassy-symbol-set!
output target
`(unres ,(lambda (n) (patcher (+ n value)))))))))
(data4
(meta-lambda
(or
(and ,@symbol? (lambda (label)
(check-label-size 4 current-byte-size 'dwords
label)
(handle-data-symbol 'abs label 0)))
(and ,@custom-reloc (lambda (a-reloc)
(check-label-size 4 current-byte-size
'dwords a-reloc)
(apply handle-data-symbol (cdr a-reloc))))
(else (lambda (data) (char/str/num data 4))))))
(data2
(meta-lambda
(or
(and ,@symbol? (lambda (label)
(check-label-size 2 current-byte-size 'words
label)
(handle-data-symbol 'abs label 0)))
(and ,@custom-reloc (lambda (a-reloc)
(check-label-size 2 current-byte-size
'words a-reloc)
(apply handle-data-symbol (cdr a-reloc))))
(else (lambda (data) (char/str/num data 2))))))
(data-item
(meta-lambda
(or
(and ,@aligner (lambda (align)
(push-stack-align (sassy-data-stack output)
align 0)
(if (> align (sassy-data-align output))
(sassy-data-align-set! output align))))
(and 'label valid-label __
(lambda (label . things)
(sassy-symbol-def-error output label)
(let ((offset (sassy-data-size output)))
(sassy-symbol-set! output label '(section data)
`(offset ,offset))
(for-each data-item things)
(sassy-symbol-set! output label
`(size ,(- (sassy-data-size output)
offset))))))
(and 'locals pair? __
(lambda (locals . body)
(let ((reset! (setup-locals locals output #f)))
(for-each data-item body)
(reset!))))
(and 'dwords __ (lambda datas (for-each data4 datas)))
(and 'bytes __ (lambda datas (for-each
(lambda (x) (char/str/num x 1))
datas)))
(and 'words __ (lambda datas (for-each data2 datas)))
(and 'qwords __ (lambda datas (for-each
(lambda (x) (char/str/num x 8))
datas)))
(and 'begin (* data-item))
(else (lambda (i) (error "sassy: bad data items" i)))))))
(for-each data-item data-list)))
(lambda (directives-list output)
(letrec
((parse-expand (lambda (itm) (parse (sassy-expand itm))))
(parse
(meta-lambda
(or
,@'void
(and 'text __ (lambda lst (process-text lst output)))
(and 'heap __ (lambda lst (process-heap lst output)))
(and 'data __ (lambda lst (process-data lst output)))
(and 'import __ (lambda lst (process-scopes
lst 'import output)))
(and 'export __ (lambda lst (process-scopes
lst 'export output)))
(and 'include __ (lambda lst (process-include lst output)))
; (and 'direcs __ (lambda lst (parse-directives lst output)))
(and 'entry ? (lambda (symb) (process-entry symb output)))
(and 'org ? (lambda (int ) (process-org int output)))
(and 'bits ? (lambda (int ) (process-bits int output)))
(and 'begin (* parse-expand))
(else (lambda (err) (error "sassy: bad directive" err)))))))
(for-each parse-expand directives-list)))))