1 ;; file warmelt-moremacro.melt -*- Lisp -*-
2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4 Copyright 2008 - 2014 Free Software Foundation, Inc.
5 Contributed by Basile Starynkevitch <basile@starynkevitch.net>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
14 GCC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>.
24 ;; the copyright notice above apply both to warmelt-moremacro.melt and
25 ;; to the generated files warmelt-moremacro*.c
28 ;; This MELT module is GPL compatible since it is GPLv3+ licensed.
29 (module_is_gpl_compatible "GPLv3+")
31 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
33 ;; This file is part of a bootstrapping compiler for the MELT lisp
34 ;; dialect, compiler which should be able to compile itself (into
35 ;; generated C file[s])
36 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
38 ;; this file should define macros which are used only later in
41 ;; the each_component_in_list macro has to be in a file after the
42 ;; expand_tuple_slice_as_tuple function
44 (defmacro each_component_in_list (sexp env mexpander modctx)
45 :doc #{Macro $EACH_COMPONENT_IN_LIST to be invoked with a
46 list-giving @var{expr} and a local variable @var{compvar} expands into
47 @code{(foreach_pair_component_in_list (@var{expr})
48 (@var{curpairvar} @var{compvar}) @var{body...})}
49 where @var{curpairvar} is fresh.}#
50 (debug "each_component_in_list macro sexp=" sexp "\n env=" debug_less env)
52 (sloc (get_field :loca_location sexp))
53 (sexcont (get_field :sexp_contents sexp))
55 (debug "each_component_in_list sloc=" debug_less sloc " sexcont=" sexcont)
56 (assert_msg "check sexcont" (is_list sexcont) sexcont)
58 (tcont (list_to_multiple sexcont discr_multiple))
59 (:long tcontlen (multiple_length tcont))
61 (debug "each_component_in_list tcont=" tcont "; tcontlen=" tcontlen)
62 (assert_msg "check tcont" (is_multiple tcont) tcont sexcont)
63 (assert_msg "check tcontlen" (>i tcontlen 0) tcontlen tcont)
65 (error_plain sloc "EACH_COMPONENT_IN_LIST <expr-list> <var-comp> too short")
68 (sexplist (let ( (se (multiple_nth tcont 1))
70 (debug "each_component_in_list sexplist=" se)
72 (svarcomp (let ( (sv (multiple_nth tcont 2))
74 (debug "each_component_in_list svarcomp=" sv)
76 (mlistexp (let ( (me (mexpander sexplist env mexpander modctx))
78 (debug "each_component_in_list mlistexp=" me)
80 (mvarcomp (let ( (mv (mexpander svarcomp env mexpander modctx))
82 (debug "each_component_in_list mvarcomp=" mv)
85 (debug "each_component_in_list tcont=" tcont
86 "\n.. before expand_tuple_slice_as_tuple=" expand_tuple_slice_as_tuple)
87 (let ( (be (expand_tuple_slice_as_tuple tcont 3 -1 env mexpander modctx))
89 (debug "each_component_in_list bodyexp=" be)
92 (when (is_not_a mvarcomp class_symbol)
93 (error_plain sloc "EACH_COMPONENT_IN_LIST <expr-list> <var-comp> bad second argument for component variable")
98 `(foreach_pair_component_in_list
100 (,curpairinlistsymb ,mvarcomp)
103 (debug "each_component_in_list resexp=" resexp)
104 (let ( (mexp (mexpander resexp env mexpander modctx))
106 (put_fields mexp :loca_location sloc)
107 (debug "each_component_in_list final mexp=" mexp)
112 (export_macro each_component_in_list)
113 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
114 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
116 (defun filtergccversion (versionstr)
117 (assert_msg "check versionstr" (is_string versionstr) versionstr )
118 (let ( (:long versionlen (string_length versionstr))
120 (:cstring gccverstr "?")
121 (:cstring gccverest "-?-")
123 ;;; versionstr should be e.g. "4.9" or "4.8"
124 ;;; melt_gccversionstr starts with e.g. "4.8 20140217" for a plugin
125 ;;; or "4.9.0 20140226" for a MELT branch
128 #{ /* filtergccversion $FILTERGCC*/
129 $GCCVERSTR = melt_gccversionstr;
130 $GCCVEREST = melt_gccversionstr+$VERSIONLEN;
132 && !strncmp (melt_string_str((melt_ptr_t)$VERSIONSTR),
135 && !ISDIGIT (melt_gccversionstr[$VERSIONLEN]))
138 (debug "filtergccversion versionlen=" versionlen " versionstr=" versionstr
139 " gccverstr='" gccverstr "'; gccverest='" gccverest "'\n.. res=" res)
143 (defun mexpand_gccif (sexpr env mexpander modctx)
144 (assert_msg "check sexpr" (is_a sexpr class_sexpr) sexpr)
145 (assert_msg "check env" (is_a env class_environment) env)
146 (debug "mexpand_gccif sexpr=" sexpr)
148 (cont (unsafe_get_field :sexp_contents sexpr))
149 (sloc (unsafe_get_field :loca_location sexpr))
150 (curpair (pair_tail (list_first cont)))
151 (curif (pair_head curpair))
152 (restpair (pair_tail curpair))
154 (debug "mexpand_gccif restpair=" restpair "\n.. first curif=" curif)
155 (if (is_a curif class_sexpr)
156 (let ( (xcurif (get_field :sexp_contents curif))
158 (debug "mexpand_gccif xcurif=" xcurif " sloc=" debug_less sloc)
163 (debug "mexpand_gccif string curif=" curif " sloc=" debug_less sloc)
164 (cond ((filtergccversion curif)
165 (debug "mexpand_gccif filtered curif=" curif)
166 (let ( (exprestlist (expand_pairlist_as_list restpair env mexpander modctx))
168 (debug "mexpand_gccif stringy exprestlist=" exprestlist)
169 (let ( (expfirst (list_first_element exprestlist))
170 (exptail (progn (list_pop_first exprestlist) exprestlist))
172 (debug "mexpand_gccif stringy return expfirst=" expfirst " exptail=" exptail)
173 (return expfirst exptail)))
176 (debug "mexpand_gccif gcc version mismatched curif=" curif " sloc=" debug_less sloc)
179 (debug "mexpand_gccif list curif=" curif " sloc=" debug_less sloc)
182 (foreach_pair_component_in_list
185 (if (not (is_string curstr))
186 (error_plain sloc "GCCIF condition not a list of strings"))
187 (if (filtergccversion curstr)
190 (debug "mexpand_gccif ok=" ok " sloc=" debug_less sloc)
192 (let ( (exprestlist (expand_pairlist_as_list restpair env mexpander modctx))
194 (debug "mexpand_gccif multicond exprestlist=" exprestlist
195 " sloc=" debug_less sloc)
196 (let ( (expfirst (list_first_element exprestlist))
197 (exptail (progn (list_pop_first exprestlist)
200 (debug "mexpand_gccif multicond return expfirst=" expfirst
201 "\n.. exptail=" exptail)
202 (shortbacktrace_dbg "mexpand_gccif multicond" 8)
203 (return expfirst exptail))
206 (debug "mexpand_gccif sexpr gcc version multicond mismatched" sexpr)
210 (error_plain sloc "GCCIF bad condition, should be a string or a list of strings")
214 (install_initial_macro 'gccif mexpand_gccif)
215 (export_macro gccif mexpand_gccif
216 :doc #{The $GCCIF macro expands the rest of the expression if the
217 version string of the GCC translating this MELT expression matches the
218 condition. Syntax is ($GCCIF condition expr...), where the condition
219 is a constant string such as "4.8" for @code{gcc-4.8} or a list of
223 ;;;; obsolete CONTAINER same as REFERENCE
225 (defun mexpandobsolete_container (sexpr env mexpander modctx)
226 (debug "mexpandobsolete_container sexpr=" sexpr)
227 (assert_msg "check sexpr" (is_a sexpr class_sexpr) sexpr)
228 (warning_plain (get_field :loca_location sexpr)
229 "obsolete use of CONTAINER in expression; use REFERENCE instead")
230 (mexpand_reference sexpr env mexpander modctx))
232 (defun patexpandobsolete_container (sexpr env pctx)
233 (debug "patexpandobsolete_container sexpr=" sexpr)
234 (assert_msg "check sexpr" (is_a sexpr class_sexpr) sexpr)
235 (warning_plain (get_field :loca_location sexpr)
236 "obsolete use of CONTAINER in pattern; use REFERENCE instead")
237 (patexpand_reference sexpr env pctx))
239 (install_initial_patmacro 'container patexpandobsolete_container mexpandobsolete_container)
240 (export_patmacro container patexpandobsolete_container mexpandobsolete_container
241 :doc #{The $CONTAINER syntax for expressions or patterns is obsolete. Use $REFERENCE instead}#)
245 ;; utility to expand an s-expression into a suitable invocation of melt_make_sexpr
246 (defun expand_quoted_sexpr (sexpr env antiquotefun mexpander modctx)
247 (debug "expand_quoted_sexpr sexpr=" sexpr)
248 (assert_msg "check sexpr" (is_a sexpr class_sexpr) sexpr)
249 (assert_msg "check env" (is_a env class_environment) env)
250 (assert_msg "check modctx" (is_object modctx) modctx)
251 (let ( (cont (unsafe_get_field :sexp_contents sexpr))
252 (loc (unsafe_get_field :loca_location sexpr))
253 (:long dline (get_int loc))
255 ((is_mixint loc) (mixint_val loc))
256 ((is_mixloc loc) (mixloc_val loc))))
257 (locexp (instance class_source_hook_call
259 :shook_called hook_melt_make_location
260 :sargop_args (tuple dfilnam (constant_box dline))))
261 (arglist (make_list discr_list))
263 (debug "expand_quoted_sexpr dline=" dline " dfilnam=" dfilnam)
264 (foreach_pair_component_in_list
267 (debug "expand_quoted_sexpr curcomp=" curcomp "\n.. arglist=" arglist)
268 (cond ( (null curcomp)
269 (list_append arglist ())
271 ( (is_integerbox curcomp)
272 (list_append arglist curcomp))
273 ( (is_string curcomp)
274 (list_append arglist curcomp))
275 ( (is_a curcomp class_keyword)
276 (list_append arglist curcomp))
277 ( (is_a curcomp class_symbol)
278 (let ( (qsymb (instance class_source_quote
282 (list_append arglist qsymb)))
283 ( (is_a curcomp class_sexpr)
284 (if (is_closure antiquotefun)
285 (let ( (curloc (unsafe_get_field :loca_location curcomp))
286 (curcont (unsafe_get_field :sexp_contents curcomp))
289 (==i (list_length curcont) 2)
290 (== (list_first_element curcont) 'comma))
291 (let ( (commaexp (list_nth_element curcont 1))
293 (debug "expand_quoted_sexpr commaexp=" commaexp " curloc=" curloc)
294 (antiquotefun commaexp arglist curloc env mexpander modctx)
295 (debug "expand_quoted_sexpr after antiquotefun arglist=" arglist)
297 (list_append arglist (expand_quoted_sexpr curcomp env antiquotefun mexpander modctx))))
298 (list_append arglist (expand_quoted_sexpr curcomp env antiquotefun mexpander modctx))
300 ;; the below cases don't happen for expressions which have
301 ;; been read, only for computed s-exprs...
303 (list_append2list arglist curcomp))
304 ( (is_multiple curcomp)
308 (list_append arglist subcomp)))
310 (list_append arglist curcomp))
312 ) ; end foreach_pair_component_in_list
313 (debug "expand_quoted_sexpr arglist=" arglist)
314 (list_prepend arglist locexp)
315 (debug "expand_quoted_sexpr final arglist=" arglist)
316 (let ( (xexp (instance class_source_apply
318 :sapp_fun 'melt_make_sexpr
319 :sargop_args (list_to_multiple arglist discr_multiple)))
321 (debug "expand_quoted_sexpr result xexp=" xexp)
327 (defun mexpand_quote (sexpr env mexpander modctx)
328 (assert_msg "check sexpr" (is_a sexpr class_sexpr) sexpr)
329 (assert_msg "check env" (is_a env class_environment) env)
330 (assert_msg "check modctx" (is_object modctx) modctx)
331 (let ( (cont (unsafe_get_field :sexp_contents sexpr))
332 (loc (unsafe_get_field :loca_location sexpr))
333 (curpair (pair_tail (list_first cont)))
334 (quoted (pair_head curpair))
336 (when (pair_tail curpair)
337 (debug "mexpand_quote polyarg sexpr=" sexpr " cont=" cont)
338 (unless (is_a sexpr class_sexpr_macrostring)
339 (warning_at loc "QUOTE used with $1 arguments outside of macro-string [as $2], consider using antiquotations"
340 (list_length cont) sexpr))
342 (restlist (make_list_from_pair discr_list curpair))
343 (newsexpr (instance class_sexpr_macrostring :sexp_contents restlist :loca_location loc))
344 (expmquo (expand_quoted_sexpr newsexpr env () mexpander modctx))
346 (debug "mexpand_quot polyarg sexpr=" sexpr " newsexpr=" newsexpr " result expmquo=" expmquo)
350 (cond ( (is_a quoted class_symbol)
356 ( (is_integerbox quoted)
359 ( (is_a quoted class_source)
360 (debug "mexpand_quote sexpr return source=" quoted)
362 ( (is_a quoted class_sexpr)
363 (debug "mexpand_quote sexpr quoted=" quoted)
364 (let ( (expquo (expand_quoted_sexpr quoted env () mexpander modctx))
366 (debug "mexpander expquo=" expquo)
369 (error_at loc "QUOTE should have a symbol, string, or integer or s-expr argument bit is $1" cont))
371 (if (is_a quoted class_keyword)
373 (let ( (squ (instance class_source_quote
378 (install_initial_macro 'quote mexpand_quote)
381 :doc #{The $QUOTE syntax (usually noted with a prefix quote-character
382 @code{'}) is for quotations. A quoted literal reifies a value, so
383 @code{'2} is a value of $DISCR_CONSTANT_INTEGER. A quoted
384 s-expression invokes $MELT_MAKE_SEXPR using
385 $HOOK_MELT_MAKE_LOCATION.}#)
388 ;; could be passed to expand_quoted_sexpr for future
389 ;; mexpand_backquote; the result of antiquoter is ignored, but it
390 ;; usually updates the arglist.
391 (defun antiquoter (aexp arglist loc env mexpander modctx)
392 (debug "antiquoter aexp=" aexp " arglist=" arglist)
393 (shortbacktrace_dbg "antiquoter" 15)
394 (let ( (mexp (mexpander aexp env mexpander modctx))
396 (debug "antiquoter mexp=" mexp)
397 (list_append arglist mexp)
399 (debug "antiquoter ends with arglist=" arglist))
404 ;;;;;;; for BACKQUOTE
405 (defun mexpand_backquote (sexpr env mexpander modctx)
406 (debug "mexpand_backquote sexpr=" sexpr)
407 (let ( (cont (unsafe_get_field :sexp_contents sexpr))
408 (loc (unsafe_get_field :loca_location sexpr))
409 (curpair (pair_tail (list_first cont)))
410 (backquoted (pair_head curpair))
412 (if (pair_tail curpair)
413 (error_plain loc "BACKQUOTE should have only one argument"_))
414 (cond ( (is_a backquoted class_sexpr)
415 (debug "mexpand_backquote backquoted sexpr " backquoted)
416 (let ( (expbk (expand_quoted_sexpr backquoted env antiquoter mexpander modctx))
418 (debug "mexpand_backquote result expbk=" expbk)
422 (debug "mexpand_backquote backquoted return verbatim " backquoted)
423 (return backquoted)))
425 (install_initial_macro 'backquote mexpand_backquote)
427 backquote mexpand_backquote
428 :doc #{The $BACKQUOTE macro is expanding into an s-expr, except for
429 $COMMA It is often noted with a prefix backquote-character
435 (defun mexpand_comma (sexpr env mexpander modctx)
436 (debug "mexpand_comma sexpr=" sexpr)
437 (let ( (cont (unsafe_get_field :sexp_contents sexpr))
438 (loc (unsafe_get_field :loca_location sexpr))
439 (curpair (pair_tail (list_first cont)))
441 (error_plain loc "COMMA outside of BACKQUOTE-d expression")
443 (install_initial_macro 'comma mexpand_comma)
446 :doc #{The $COMMA macro is related to $BACKQUTE.
447 $COMMA It is often noted with a prefix comma-character
451 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
452 ;;; utility function, e.g. to substitute *some* symbols in macrostrings.
453 (defun substitute_sexpr (sexpr symbrepf insidef)
454 :doc #{The $SUBSTITUTE_SEXPR is substituting some symbols inside the
455 given $SEXPR. Each symbol inside $SEXPR is passed to the $SYMBREPF
456 function which can return a list or a tuple to be replaced by
457 @i{several} -or none- elements. When a component of $SEXPR is itself
458 an s-expression, the function $INSIDEF, if given, decides -by
459 returning non-nil- if the substitution goes inside recursively. By
460 default the substitution does not recurse inside inner
462 (debug "substitute_sexpr" " sexpr=" sexpr)
463 (when (is_not_a sexpr class_sexpr)
464 (debug "substitute_sexpr" " not an S-expr:" sexpr)
466 (let ( (clist (make_list discr_list))
467 (cont (unsafe_get_field :sexp_contents sexpr))
468 (loc (unsafe_get_field :loca_location sexpr))
469 (newsexpr (if (is_a sexpr class_sexpr_macrostring)
470 (instance class_sexpr_macrostring
472 :sexp_contents clist)
473 (instance class_sexpr
475 :sexp_contents clist)))
477 (each_component_in_list
480 (debug "substitute_sexpr" " curcont=" curcont)
482 ( (is_a curcont class_keyword)
483 (list_append clist curcont))
484 ( (is_a curcont class_symbol)
485 (let ( (repsymb (if (is_closure symbrepf)
490 ( (is_multiple repsymb)
494 (list_append clist currep)
499 (each_component_in_list
502 (list_append clist curlrep))
505 (list_append clist repsymb))))
507 ( (is_a curcont class_sexpr)
509 (insidev (if (is_closure insidef) (insidef curcont)))
510 (replcont (if insidev (substitute_sexpr curcont symbrepf insidef) curcont))
513 ( (is_multiple replcont)
517 (list_append clist curins)))
519 (each_component_in_list
522 (list_append clist subcont)))
524 (list_append clist replcont)))
528 (list_append clist curcont)
533 (debug "substitute_sexpr" " result newsexpr=" newsexpr)
537 (export_values substitute_sexpr)
538 ;; eof warmelt-moremacro.melt