File: keyarg.mac

package info (click to toggle)
maxima 5.49.0-1~exp1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 128,980 kB
  • sloc: lisp: 437,854; fortran: 14,665; tcl: 10,143; sh: 4,598; makefile: 2,204; ansic: 447; java: 374; python: 262; perl: 201; xml: 60; awk: 28; sed: 15; javascript: 2
file content (58 lines) | stat: -rw-r--r-- 1,922 bytes parent folder | download | duplicates (18)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/*-*-macsyma-*-*/

/* macros to define functions which take their arguments
   via keywords. */

eval_when([translate,batch,demo],
	  load_package(sharem,"autolo"))$

herald_package(keyarg)$

/* The idea is to be able to say:

  FOO(X_ZONE=3.3, LOGLIN, FOOSWITCH, BAR=0)

  Specify the arguments/options to a function in terms of
  keywords.

And have unspecified arguments default. */


def_keyarg(header,body)::=
 buildq([mname:part(header,0), body,
         sname:concat(part(header,0),"-internal"),
         sargs:maplist(lambda([u],if atom(u) then u else part(u,1)),
	               args(header)),
         dispatch:maplist(lambda([u],if atom(u) then ['key_atom,[u]]
	                                else ['key_pair,[part(u,1),part(u,2)]]),
			  args(header))],
	(eval_when(loadfile,
	           setup_autoload("keyarg",translate_keyarg)),
         put('mname,'dispatch,'translate_keyarg),
         mname([macro_argl])::=translate_keyarg(macro_argl,'mname,'sname),
	 sname(splice(sargs)):=body))$

/* This routine must be around during the macro-expansion */

translate_keyarg(macro_argl,mname,sname):=
 /* for now I am not going to do the order-of-evaluation guarantee */
 block([sargl:[],temp,dispatch:get(mname,'translate_keyarg)],
       for d in dispatch
       do(temp:apply(d[1],cons(macro_argl,d[2])),
          push(temp[1],sargl),
	  macro_argl:temp[2]),
       if not macro_argl=[] then error("unknown arguments to",mname,":",macro_argl),
       funmake(sname,reverse(sargl)))$

key_indicator(argl,atom,value):=
 (for a in argl
  do(if atom(a) then(if a=atom then(value:true,argl:delete(a,argl),return(done)))
     else if part(a,1)=atom then(value:part(a,2),argl:delete(a,argl),return(done))),
  [value,argl])$     

/* I am thinking of having KEY_ATOM and KEY_PAIR do different things. */

key_atom(argl,atom):=key_indicator(argl,atom,false)$

key_pair(argl,atom,value):=key_indicator(argl,atom,value)$