1 """cl2py.py: Translate IRAF CL program to Python
2
3 $Id: cl2py.py 1244 2010-07-26 18:43:58Z sontag $
4
5 R. White, 1999 December 20
6 """
7 from __future__ import division
8
9 import cStringIO, os, sys
10
11 from generic import GenericASTTraversal
12 from clast import AST
13 from cltoken import Token
14 import clscan, clparse
15 from clcache import codeCache
16
17 from pytools.irafglobals import Verbose
18 from pytools import basicpar, minmatch, irafutils
19 import irafpar, pyrafglobals
20
21
22
23
24
25
26
27
28
29 _parser = None
30
31 -def cl2py(filename=None, string=None, parlist=None, parfile="", mode="proc",
32 local_vars_dict=None, local_vars_list=None, usecache=1):
33
34 """Read CL program from file and return pycode object with Python equivalent
35
36 filename: Name of the CL source file or a filehandle from which the
37 source code can be read.
38 string: String containing the source code. Either filename or string must be
39 specified; if both are specified, only filename is used
40 parlist: IrafParList object with list of parameters (which may have already
41 been defined from a .par file)
42 parfile: Name of the .par file used to define parlist. parlist may be
43 defined even if parfile is null, but a null parfile is interpreted
44 to mean that the parameter definitions in the CL script should
45 override the parlist. If parfile is not null, it is an error if
46 the CL script parameters conflict with the parlist.
47 mode: Mode of translation. Default "proc" creates a procedure script
48 (which defines a Python function.) Normally CL scripts will be
49 translated using this default. If mode is "single" then the
50 necessary environment is assumed to be set and the Python
51 code simply gets executed directly. This is used in the
52 CL compatibility mode and other places where a single line of
53 CL must be executed.
54 Mode also determines whether parameter sets are saved in calls
55 to CL tasks. In "single" mode parameters do get saved; in
56 "proc" mode they do not get saved. This is intended to be
57 consistent with the behavior of the IRAF CL, where parameter
58 changes in scripts are not preserved.
59 local_vars_dict, local_vars_list: Initial definitions of local variables.
60 May be modified by declarations in the CL code. This is used only for
61 "single" mode to allow definitions to persist across statements.
62 usecache: Set to false value to omit use of code cache for either saving
63 or retrieving code. This is useful mainly for compiler testing.
64 """
65
66 global _parser, codeCache
67
68 if _parser is None:
69 _parser = clparse.getParser()
70
71 if mode not in ["proc", "single"]:
72 raise ValueError("Mode = `%s', must be `proc' or `single'" % (mode,))
73
74 if not filename in (None, ''):
75 if isinstance(filename,str):
76 efilename = os.path.expanduser(filename)
77 if usecache:
78 index, pycode = codeCache.get(efilename,mode=mode)
79 if pycode is not None:
80 if Verbose>1:
81 print efilename,"filename found in CL script cache"
82 return pycode
83 else:
84 index = None
85 fh = open(efilename)
86 clInput = fh.read()
87 fh.close()
88 elif hasattr(filename,'read'):
89 clInput = filename.read()
90 if usecache:
91 index, pycode = codeCache.get(filename,mode=mode,source=clInput)
92 if pycode is not None:
93 if Verbose>1:
94 print filename,"filehandle found in CL script cache"
95 return pycode
96 else:
97 index = None
98 if hasattr(filename,'name'):
99 efilename = filename.name
100 else:
101 efilename = ''
102 else:
103 raise TypeError('filename must be a string or a filehandle')
104 elif string is not None:
105
106
107 clInput = string
108 efilename = 'string_proc'
109 if usecache:
110 index, pycode = codeCache.get(None,mode=mode,source=clInput)
111 if pycode is not None:
112 if Verbose>1:
113 print "Found in CL script cache: ",clInput.strip()[:20]
114 return pycode
115 else:
116 index = None
117 else:
118 raise ValueError('Either filename or string must be specified')
119
120 if mode == "single":
121 taskObj = 'cl'
122 else:
123 taskObj = None
124
125
126 scanner = clscan.CLScanner()
127 tokens = scanner.tokenize(clInput)
128 tree = _parser.parse(tokens, fname=efilename)
129
130 tree.filename = efilename
131
132
133 vars = VarList(tree,mode,local_vars_list,local_vars_dict,parlist)
134
135
136
137 _checkVars(vars, parlist, parfile)
138
139
140
141 TypeCheck(tree, vars, efilename)
142
143
144 tree2python = Tree2Python(tree, vars, efilename, taskObj)
145
146
147
148 pycode = Pycode(tree2python)
149
150
151 if index is not None: codeCache.add(index, pycode)
152 pycode.index = index
153 if Verbose>1:
154 print "File `%s' compiled by cl2py" % efilename
155 return pycode
156
158
159 """Returns true if pycode is up-to-date"""
160
161 global codeCache
162 if pycode is None:
163 return 0
164 index = codeCache.getIndex(filename)
165 return (index is not None) and (pycode.index == index)
166
167
169
170 """Simple container class (no methods) for holding picklable objects"""
171
172 pass
173
174
176
177 """Container for Python CL translation"""
178
180
181 self.code = tree2python.code
182 self.vars = Container()
183 self.vars.local_vars_dict = tree2python.vars.local_vars_dict
184 self.vars.local_vars_list = tree2python.vars.local_vars_list
185 self.vars.parList = tree2python.vars.parList
186 self.vars.proc_name = tree2python.vars.proc_name
187 self.vars.has_proc_stmt = tree2python.vars.has_proc_stmt
188
190
191 """Set the filename used for parameter list
192
193 This is used by codeCache, which needs to be able to read a Pycode
194 object created from some other file and attach it to the current file.
195 """
196
197 self.vars.parList.setFilename(filename)
198
199
201 """Check variable list for consistency with the given parlist"""
202
203
204
205
206
207 if (not parfile) or (parlist is None): return
208
209
210
211
212
213 if vars.has_proc_stmt and not parlist.isConsistent(vars.parList):
214
215
216
217
218
219
220 if Verbose>0:
221 sys.stdout.flush()
222 sys.stderr.write("Parameters from CL code inconsistent "
223 "with .par file for task %s\n" % vars.getProcName())
224 sys.stderr.flush()
225
226
227 plist = parlist.getParList()
228 newlist = []
229 newdict = {}
230 for par in plist:
231 newlist.append(par.name)
232 newdict[par.name] = Variable(irafParObject=par)
233 vars.proc_args_list = newlist
234 vars.proc_args_dict = newdict
235
236 vars.addSpecialArgs()
237
238 vars.checkLocalConflict()
239 vars.parList = parlist
240
242
243 """Helper class to find first line number in an AST"""
244
246
254
256 if hasattr(node,'lineno'):
257 self.lineno = node.lineno
258 raise self.FoundIt
259
261
262 """Mixin class that does error tracking during AST traversal"""
263
265 self.errlist = []
266 self.warnlist = []
267
268 - def error(self, msg, node=None):
269
270 """Add error to the list with line number"""
271
272 if not hasattr(self, 'errlist'): self._error_init()
273 self.errlist.append((self.getlineno(node),msg))
274
275 - def warning(self, msg, node=None):
276
277 """Add warning to the list with line number"""
278
279 if not hasattr(self, 'errlist'): self._error_init()
280 self.warnlist.append((self.getlineno(node),"Warning: %s" % msg))
281
283
284 if node:
285 return FindLineNumber(node).lineno
286 else:
287 return 0
288
290
291 """Add errors from another ErrorTracker"""
292
293 if not hasattr(other, 'errlist'): return
294 if not hasattr(self, 'errlist'): self._error_init()
295 self.errlist.extend(other.errlist)
296 self.warnlist.extend(other.warnlist)
297
299
300 """Print all warnings and errors and raise SyntaxError if errors were found"""
301
302 if not hasattr(self,'errlist'):
303 return
304 if self.errlist:
305 self.errlist.extend(self.warnlist)
306 self.errlist.sort()
307 try:
308 errmsg = ["Error in CL script %s" % self.filename]
309 except AttributeError:
310 errmsg = ["Error in CL script"]
311 for lineno, msg in self.errlist:
312 if lineno:
313 errmsg.append("%s (line %d)" % (msg, lineno))
314 else:
315 errmsg.append(msg)
316 raise SyntaxError("\n".join(errmsg))
317 elif self.warnlist:
318 self.warnlist.sort()
319 try:
320 warnmsg = ["Warning in CL script %s" % self.filename]
321 except AttributeError:
322 warnmsg = ["Warning in CL script"]
323 for lineno, msg in self.warnlist:
324 if lineno:
325 warnmsg.append("%s (line %d)" % (msg, lineno))
326 else:
327 warnmsg.append(msg)
328 warnmsg = "\n".join(warnmsg)
329 sys.stdout.flush()
330 sys.stderr.write(warnmsg)
331 if warnmsg[-1:] != '\n': sys.stderr.write('\n')
332
333
335
336 """Extract name and args from procedure statement"""
337
341
343
344 self.proc_name = node[1].attr
345 self.proc_args_list = []
346 if len(node[2]):
347 self.preorder(node[2])
348 self.prune()
349
351 self.proc_args_list.append(irafutils.translateName(node.attr))
352
353 _longTypeName = {
354 "s": "string",
355 "f": "file",
356 "struct": "struct",
357 "i": "int",
358 "b": "bool",
359 "r": "real",
360 "d": "double",
361 "gcur": "gcur",
362 "imcur": "imcur",
363 "ukey": "ukey",
364 "pset": "pset",
365 }
366
368
369 """Container for properties of a variable"""
370
371 - def __init__(self, name=None, type=None, mode="h", array_size=None,
372 init_value=None, list_flag=0, min=None, max=None,
373 prompt=None, enum=None, irafParObject=None):
374 if irafParObject is not None:
375
376 ipo = irafParObject
377 self.name = ipo.name
378 if ipo.type[:1] == "*":
379 self.type = _longTypeName[ipo.type[1:]]
380 self.list_flag = 1
381 else:
382 self.type = _longTypeName[ipo.type]
383 self.list_flag = 0
384 if isinstance(ipo, basicpar.IrafArrayPar):
385 self.shape = ipo.shape
386 else:
387 self.shape = None
388 self.init_value = ipo.value
389 self.options = minmatch.MinMatchDict({
390 "mode": ipo.mode,
391 "min": ipo.min,
392 "max": ipo.max,
393 "prompt": ipo.prompt,
394 "enum": ipo.choice,
395 "length": None, })
396 else:
397
398 self.name = name
399 self.type = type
400 self.shape = array_size
401 self.list_flag = list_flag
402 self.options = minmatch.MinMatchDict({
403 "mode": mode,
404 "min": min,
405 "max": max,
406 "prompt": prompt,
407 "enum": enum,
408 "length": None, })
409 self.init_value = init_value
410
412 """Get name without translations"""
413 return irafutils.untranslateName(self.name)
414
415 - def toPar(self, strict=0):
416 """Convert this variable to an IrafPar object"""
417 return irafpar.makeIrafPar(self.init_value,
418 datatype=self.type,
419 name=self.getName(),
420 array_size=self.shape,
421 list_flag=self.list_flag,
422 mode=self.options["mode"],
423 min=self.options["min"],
424 max=self.options["max"],
425 enum=self.options["enum"],
426 prompt=self.options["prompt"],
427 strict=strict)
428
430 """Return a string usable as parameter declaration with
431 default value in the function definition statement"""
432
433 name = irafutils.translateName(self.name)
434 if self.shape is None:
435 if self.init_value is None:
436 return name + "=None"
437 else:
438 return name + "=" + `self.init_value`
439 else:
440
441 arg = name + "=["
442 if self.init_value is None:
443 arglist = ["INDEF"]*len(self)
444 else:
445 arglist = []
446 for iv in self.init_value:
447 arglist.append(`iv`)
448 return arg + ", ".join(arglist) + "]"
449
450 - def parDefLine(self, filename=None, strict=0, local=0):
451 """Return a list of string arguments for makeIrafPar"""
452
453 name = irafutils.translateName(self.name)
454 arglist = [name,
455 "datatype=" + `self.type`,
456 "name=" + `self.getName()` ]
457
458
459 if local:
460 arglist[0] = `self.init_value`
461 self.options["mode"] = "u"
462 if self.shape is not None:
463 arglist.append("array_size=" + `self.shape`)
464 if self.list_flag:
465 arglist.append("list_flag=" + `self.list_flag`)
466 keylist = self.options.keys()
467 keylist.sort()
468 for key in keylist:
469 option = self.options[key]
470 if option is not None:
471 arglist.append(key + "=" + `self.options[key]`)
472 if filename: arglist.append("filename=" + `filename`)
473 if strict: arglist.append("strict=" + `strict`)
474 return arglist
475
477 s = self.type + " "
478 if self.list_flag: s = s + "*"
479 s = s + self.name
480 if self.init_value is not None:
481 s = s + " = " + `self.init_value`
482 optstring = "{"
483 for key, value in self.options.items():
484 if (value is not None) and (key != "mode" or value != "h"):
485
486 optstring = optstring + " " + key + "=" + str(value)
487 if len(optstring) > 1:
488 s = s + " " + optstring + " }"
489 return s
490
492 array_size = 1
493 if self.shape:
494 for d in self.shape:
495 array_size = array_size*d
496 return array_size
497
499
500 """Extract list of variable definitions from parameter block"""
501
510
512 self.current_type = node[0].attr
513
515
516 if len(node)>1:
517 return self._get_dims(node[0]) + (int(node[2]),)
518 else:
519 return (int(node[0]),)
520
522 var_name = node[1]
523 name = irafutils.translateName(var_name[0].attr)
524 if len(var_name) > 1:
525
526 shape = tuple(self._get_dims(var_name[2]))
527 else:
528
529
530 shape = None
531 if self.var_dict.has_key(name):
532 if self.var_dict[name]:
533 self.error("Variable `%s' is multiply declared" % name, node)
534 self.prune()
535 else:
536
537
538 self.var_dict[name] = Variable(name, self.current_type,
539 array_size=shape, mode="a")
540 else:
541 self.var_list.append(name)
542 self.var_dict[name] = Variable(name, self.current_type,
543 array_size=shape)
544 self.current_var = self.var_dict[name]
545 self.preorder(node[0])
546 self.preorder(node[2])
547 self.preorder(node[3])
548 self.prune()
549
551 if len(node) > 0:
552 self.current_var.list_flag = 1
553 self.prune()
554
556
557 if self.current_var.init_value is not None:
558
559 errmsg = \
560 "%s: Variable `%s' has more than one set of initial values" % \
561 (self.filename, self.current_var.name,)
562 self.error(errmsg, node)
563 else:
564 self.current_var.init_value = []
565
567
568
569 v = self.current_var
570 ilist = v.init_value
571 if len(ilist) == 1 and v.shape is None:
572 try:
573 v.init_value = _convFunc(v, ilist[0])
574 except ValueError, e:
575 self.error("Bad initial value for variable `%s': %s" %
576 (v.name, e), node)
577 else:
578
579 if v.shape is None:
580 v.shape = (len(ilist),)
581 elif len(v) > len(ilist):
582 for i in range(len(v)-len(ilist)):
583 v.init_value.append(None)
584 elif len(v) < len(ilist):
585 self.error("Variable `%s' has too many initial values" % (v.name,), node)
586 else:
587 try:
588 for i in range(len(v.init_value)):
589 v.init_value[i] = _convFunc(v, v.init_value[i])
590 except ValueError, e:
591 self.error("Bad initial value for array variable `%s': %s" %
592 (v.name, e), node)
593
595
596 vnode = node[0]
597 if isinstance(vnode, Token):
598 self.current_var.init_value.append(vnode)
599 else:
600
601 self.current_var.init_value.append(
602 Token(type=vnode[1].type, attr=vnode[0].type+vnode[1].attr,
603 lineno=vnode[0].lineno))
604 self.prune()
605
607 optname = node[0].attr
608 vnode = node[2]
609 if isinstance(vnode, Token):
610 optvalue = vnode.get()
611 else:
612
613 if vnode[0] == "-":
614 optvalue = - vnode[1].get()
615 else:
616 optvalue = vnode[1].get()
617 optdict = self.current_var.options
618 if not optdict.has_key(optname):
619 errmsg = "Unknown option `%s' for variable `%s'" % (optname, self.current_var.name)
620 self.error(errmsg, node)
621 else:
622 optdict[optname] = optvalue
623 self.prune()
624
625
626
627
628 _SpecialArgs = {
629 'taskObj': None,
630 }
631
632 -class VarList(GenericASTTraversal, ErrorTracker):
633
634 """Scan tree and get info on procedure, parameters, and local variables"""
635
636 - def __init__(self, ast, mode="proc", local_vars_list=None,
637 local_vars_dict=None, parlist=None):
638 GenericASTTraversal.__init__(self, ast)
639 self.mode = mode
640 self.proc_name = ""
641 self.proc_args_list = []
642 self.proc_args_dict = {}
643 self.has_proc_stmt = 0
644 if local_vars_list is None:
645 self.local_vars_list = []
646 self.local_vars_count = 0
647 else:
648 self.local_vars_list = local_vars_list
649 self.local_vars_count = len(local_vars_list)
650 if local_vars_dict is None:
651 self.local_vars_dict = {}
652 else:
653 self.local_vars_dict = local_vars_dict
654 if hasattr(ast, 'filename'):
655 self.filename = ast.filename
656 else:
657 self.filename = ''
658 self.input_parlist = parlist
659 self.preorder()
660 del self.input_parlist
661
662
663
664
665
666 if self.mode != "single" and not self.proc_name:
667 if not self.filename:
668 self.proc_name = 'proc'
669 else:
670 path, fname = os.path.split(self.filename)
671 root, ext = os.path.splitext(fname)
672 self.setProcName(root)
673
674
675 self.addSpecialArgs()
676
677
678 self.checkLocalConflict()
679
680 self.printerrors()
681
682
683 p = []
684 for var in self.proc_args_list:
685 if not _SpecialArgs.has_key(var):
686 arg = self.proc_args_dict[var].toPar()
687 p.append(arg)
688 self.parList = irafpar.IrafParList(self.getProcName(),
689 filename=self.filename, parlist=p)
690
692 """Check both local and procedure dictionaries for this name"""
693 return self.proc_args_dict.has_key(name) or \
694 self.local_vars_dict.has_key(name)
695
696 - def get(self, name):
697 """Return entry from local or procedure dictionary (None if none)"""
698 return self.proc_args_dict.get(name) or self.local_vars_dict.get(name)
699
701 """Set procedure name"""
702
703 pdot = proc_name.find('.')
704 if pdot==0:
705 self.error("Illegal procedure name `%s' starts with `.'" % proc_name, node)
706 if pdot >= 0:
707 self.warning("Bad procedure name `%s' truncated after dot to `%s'" %
708 (proc_name, proc_name[:pdot]), node)
709 proc_name = proc_name[:pdot]
710
711
712 self.proc_name = irafutils.translateName(proc_name)
713
715 """Get procedure name, undoing translations"""
716 return irafutils.untranslateName(self.proc_name)
717
719
720 if self.proc_args_dict.has_key(name):
721 self.proc_args_list.remove(name)
722 del self.proc_args_dict[name]
723
724 targ = irafutils.translateName(name)
725 if not self.proc_args_dict.has_key(targ):
726 self.proc_args_list.append(targ)
727 self.proc_args_dict[targ] = Variable(targ, type, init_value=value)
728
730 """Add mode, $nargs, other special parameters to all tasks"""
731
732 if not self.proc_args_dict.has_key('mode'):
733 self.proc_args_list.append('mode')
734 self.proc_args_dict['mode'] = Variable('mode','string',
735 init_value='al')
736
737 self.addSpecial("$nargs", 'int', 0)
738
739
740
741
742
743
744 for parg, ivalue in _SpecialArgs.items():
745 if not self.proc_args_dict.has_key(parg):
746 self.proc_args_list.append(parg)
747 self.proc_args_dict[parg] = ivalue
748
750 """Check for local variables that conflict with parameters"""
751
752 errlist = ["Error in procedure `%s'" % self.getProcName()]
753 for v in self.local_vars_list:
754 if self.proc_args_dict.has_key(v):
755 errlist.append(
756 "Local variable `%s' overrides parameter of same name" %
757 (v,))
758 if len(errlist) > 1:
759 self.error("\n".join(errlist))
760
762 """List variables"""
763 print "Procedure arguments:"
764 for var in self.proc_args_list:
765 v = self.proc_args_dict[var]
766 if _SpecialArgs.has_key(var):
767 print 'Special',var,'=',v
768 else:
769 print v
770 print "Local variables:"
771 for var in self.local_vars_list:
772 print self.local_vars_dict[var]
773
775 """Return procedure arguments as IrafParList"""
776 return self.parList
777
779 self.has_proc_stmt = 1
780
781 p = ExtractProcInfo(node)
782 self.setProcName(p.proc_name, node)
783 self.proc_args_list = p.proc_args_list
784 for arg in self.proc_args_list:
785 if self.proc_args_dict.has_key(arg):
786 errmsg = "Argument `%s' repeated in procedure statement %s" % \
787 (arg,self.getProcName())
788 self.error(errmsg, node)
789 else:
790 self.proc_args_dict[arg] = None
791 self.prune()
792
794
795 p = ExtractDeclInfo(node, self.proc_args_list, self.proc_args_dict,
796 self.ast.filename)
797
798 d = self.proc_args_dict
799 for arg in d.keys():
800 if not d[arg]:
801
802 d[arg] = self.getFromInputList(arg)
803 if not d[arg]:
804 errmsg = "Procedure argument `%s' is not declared" % (arg,)
805 self.error(errmsg, node)
806 self.prune()
807
813
815
816 p = ExtractDeclInfo(node, self.local_vars_list, self.local_vars_dict,
817 self.ast.filename)
818 self.prune()
819
820
821
822
823 _typeDict = {
824 'int': 'int',
825 'real': 'float',
826 'double': 'float',
827 'bool': 'bool',
828 'string': 'string',
829 'char': 'string',
830 'struct': 'string',
831 'file': 'string',
832 'gcur': 'string',
833 'imcur': 'string',
834 'ukey': 'string',
835 'pset': 'unknown',
836 }
837
838
839
840
841
842 _rfuncDict = {
843 'int': {'int': None,
844 'float': None,
845 'string': 'int',
846 'bool': None,
847 'unknown': 'int',
848 'indef': None},
849 'float': {'int': None,
850 'float': None,
851 'string': 'float',
852 'bool': 'float',
853 'unknown': 'float',
854 'indef': None},
855 'string':{'int': 'str',
856 'float': 'str',
857 'string': None,
858 'bool': 'iraf.bool2str',
859 'unknown': 'str',
860 'indef': None},
861 'bool': {'int': 'iraf.boolean',
862 'float': 'iraf.boolean',
863 'string': 'iraf.boolean',
864 'bool': None,
865 'unknown': 'iraf.boolean',
866 'indef': None},
867 'indef': {'int': None,
868 'float': None,
869 'string': None,
870 'bool': None,
871 'unknown': None,
872 'indef': None},
873 'unknown': {'int': None,
874 'float': None,
875 'string': None,
876 'bool': None,
877 'unknown': None,
878 'indef': None},
879 }
880
883
884
885
886
887
888 _numberTypes = ['float', 'int', 'unknown']
889
891 if node1.exprType in _numberTypes:
892 if node2.exprType not in _numberTypes:
893 rv = node1.exprType
894 node2.requireType = rv
895 else:
896
897
898 if 'float' in [node1.exprType, node2.exprType]:
899 rv = 'float'
900 elif 'unknown' in [node1.exprType, node2.exprType]:
901 rv = 'unknown'
902 else:
903 rv = node1.exprType
904 else:
905 if node2.exprType in _numberTypes:
906 rv = node2.exprType
907 node1.requireType = rv
908 else:
909 rv = 'float'
910 node1.requireType = rv
911 node2.requireType = rv
912 return rv
913
914
915
917 if node.exprType in _numberTypes:
918 return node.exprType
919 else:
920 node.requireType = 'float'
921 return node.requireType
922
923 _CLVarDict = {}
924
926 """Returns CL parameter data type if this is a CL variable, "unknown" if not
927
928 Note that this can be incorrect about the data type for CL variables
929 that are masked by package level variables. Too bad, that is just
930 too ugly to be believed anyway. Don't do that.
931 """
932 global _CLVarDict
933 try:
934 if not _CLVarDict:
935 import iraf
936 d = iraf.cl.getParDict()
937
938
939 for pname, pobj in d.items():
940 iraftype = pobj.type
941 if iraftype[:1] == "*":
942 iraftype = iraftype[1:]
943 _CLVarDict[pname] = _typeDict[_longTypeName[iraftype]]
944 except AttributeError:
945 pass
946 return _CLVarDict.get(name, "unknown")
947
949
950 """Determine types of all expressions"""
951
952 - def __init__(self, ast, vars, filename):
957
958
959
961 node.exprType = 'float'
962 node.requireType = node.exprType
964 node.exprType = 'int'
965 node.requireType = node.exprType
967 node.exprType = 'float'
968 node.requireType = node.exprType
970 node.exprType = 'indef'
971 node.requireType = node.exprType
973 node.exprType = 'string'
974 node.requireType = node.exprType
976 node.exprType = 'string'
977 node.requireType = node.exprType
979 node.exprType = 'string'
980 node.requireType = node.exprType
982 node.exprType = 'bool'
983 node.requireType = node.exprType
984
986 s = irafutils.translateName(node.attr)
987 v = self.vars.get(s)
988 if v is not None:
989 node.exprType = _typeDict[v.type]
990 node.requireType = node.exprType
991 else:
992
993
994 node.exprType = _getCLVarType(node.attr)
995 node.requireType = node.exprType
996
998 node.exprType = node[0].exprType
999 node.requireType = node.exprType
1000
1002 functionname = node[0].attr
1003 ftype = _functionType.get(functionname)
1004 if ftype is None: ftype = 'unknown'
1005 node.exprType = ftype
1006 node.requireType = node.exprType
1007
1009 assert len(node)==3
1010 node.exprType = node[1].exprType
1011 node.requireType = node.exprType
1012
1014 assert len(node)==3
1015 node.exprType = _arithType(node[0], node[2])
1016 node.requireType = node.exprType
1017
1019 assert len(node)==2
1020 node.exprType = _numberType(node[1])
1021 node.requireType = node.exprType
1022
1024 assert len(node)==3
1025 node.exprType = _arithType(node[0], node[2])
1026 node.requireType = node.exprType
1027
1029 assert len(node)==3
1030 node.exprType = 'string'
1031 node.requireType = node.exprType
1032 node[0].requireType = 'string'
1033 node[2].requireType = 'string'
1034
1036 assert len(node)==3
1037 if node[1].type == '-':
1038 node.exprType = _arithType(node[0], node[2])
1039 node.requireType = node.exprType
1040 else:
1041
1042 if node[0].exprType == 'string' or node[2].exprType == 'string':
1043 node.exprType = 'string'
1044 node.requireType = node.exprType
1045 node[0].requireType = 'string'
1046 node[2].requireType = 'string'
1047 else:
1048 node.exprType = _arithType(node[0], node[2])
1049 node.requireType = node.exprType
1050
1052 assert len(node) == 3
1053 node.exprType = 'bool'
1054 node.requireType = node.exprType
1055
1057 assert len(node) == 2
1058 node.exprType = 'bool'
1059 node.requireType = node.exprType
1060 node[1].requireType = 'bool'
1061
1063 assert len(node) == 3
1064 node.exprType = 'bool'
1065 node.requireType = node.exprType
1066 node[0].requireType = 'bool'
1067 node[2].requireType = 'bool'
1068
1070 assert len(node) == 3
1071 node[2].requireType = node[0].exprType
1072
1074
1075 """Helper class to store block structure info for GOTO analysis"""
1076
1077 - def __init__(self, node, blockid, parent):
1078 self.node = node
1079 self.blockid = blockid
1080 self.parent = parent
1081
1083
1084 """AST traversal for CL GOTO analysis
1085
1086 Analyze GOTO structure looking for branches into blocks (which are forbidden),
1087 backward branches (which are not supported), and other errors. Adds information
1088 to the AST that is used to generate Python equivalent code.
1089 """
1090
1092 GenericASTTraversal.__init__(self, ast)
1093 self.blocks = []
1094 self.label_blockid = {}
1095 self.goto_blockidlist = {}
1096 self.goto_nodelist = {}
1097 self.current_blockid = -1
1098
1099
1100 self.preorder()
1101
1102
1103 for label in self.goto_blockidlist.keys():
1104 if not self.label_blockid.has_key(label):
1105 node = self.goto_nodelist[label][0]
1106 self.error("GOTO refers to unknown label `%s'" % label, node)
1107
1108
1109
1110
1111 label_count = [0]*len(self.blocks)
1112 for label, ib in self.label_blockid.items():
1113
1114 if self.goto_blockidlist.has_key(label):
1115 label_count[ib] += 1
1116 for ib in range(len(self.blocks)):
1117 self.blocks[ib].node.label_count = label_count[ib]
1118
1119
1120
1121
1122
1124 """Get a list of known labels used in GOTOs"""
1125 labels = self.goto_blockidlist.keys()
1126 labels.sort()
1127 return labels
1128
1130 """Check if label is used in a GOTO"""
1131 return self.goto_blockidlist.has_key(label)
1132
1133
1134
1135
1136
1138 newid = len(self.blocks)
1139 self.blocks.append(BlockInfo(node, newid, self.current_blockid))
1140 self.current_blockid = newid
1141
1143 newid = len(self.blocks)
1144 self.blocks.append(BlockInfo(node, newid, self.current_blockid))
1145 self.current_blockid = newid
1146
1148 self.current_blockid = self.blocks[self.current_blockid].parent
1149
1151 self.current_blockid = self.blocks[self.current_blockid].parent
1152
1154 label = node[0].attr
1155 if self.label_blockid.has_key(label):
1156 self.error("Duplicate statement label `%s'" % label, node)
1157 else:
1158 cblockid = self.current_blockid
1159 self.label_blockid[label] = cblockid
1160
1161 for i in self.goto_blockidlist.get(label,[]):
1162 if self.blocks[i].blockid < cblockid:
1163 self.error("GOTO branches to label `%s' in inner block"
1164 % label, node)
1165
1167 label = str(node[1])
1168 if self.label_blockid.has_key(label):
1169 self.error("Backwards GOTO to label `%s' is not allowed" % label, node)
1170 elif self.goto_blockidlist.has_key(label):
1171 self.goto_blockidlist[label].append(self.current_blockid)
1172 self.goto_nodelist[label].append(node)
1173 else:
1174 self.goto_blockidlist[label] = [self.current_blockid]
1175 self.goto_nodelist[label] = [node]
1176
1177
1178
1179 _translateList = {
1180 "{": "",
1181 "}": "",
1182 ";": "",
1183 "!": "not ",
1184 "//": " + ",
1185 }
1186
1187
1188
1189 _taskList = {
1190 "print" : "clPrint",
1191 "_curpack" : "curpack",
1192 "_allocate" : "clAllocate",
1193 "_deallocate" : "clDeallocate",
1194 "_devstatus" : "clDevstatus",
1195 }
1196
1197
1198
1199
1200 _functionList = {
1201 "int": "iraf.integer",
1202 "str": "str",
1203 "abs": "iraf.absvalue",
1204 "min": "iraf.minimum",
1205 "max": "iraf.maximum",
1206 }
1207
1208
1209
1210 _functionType = {
1211 "int": "int",
1212 "real": "float",
1213 "sin": "float",
1214 "cos": "float",
1215 "tan": "float",
1216 "atan2": "float",
1217 "exp": "float",
1218 "log": "float",
1219 "log10": "float",
1220 "sqrt": "float",
1221 "frac": "float",
1222 "abs": "float",
1223 "min": "unknown",
1224 "max": "unknown",
1225 "fscan": "int",
1226 "scan": "int",
1227 "fscanf": "int",
1228 "scanf": "int",
1229 "nscan": "int",
1230 "stridx": "int",
1231 "strlen": "int",
1232 "str": "string",
1233 "substr": "string",
1234 "envget": "string",
1235 "mktemp": "string",
1236 "radix": "string",
1237 "osfn": "string",
1238 "_curpack": "string",
1239 "defpar": "bool",
1240 "access": "bool",
1241 "defvar": "bool",
1242 "deftask": "bool",
1243 "defpac": "bool",
1244 "imaccess": "bool",
1245 }
1246
1247
1248 _LogOpDict = {
1249 "&&": " and ",
1250 "||": " or ",
1251 }
1252
1253
1254 _RedirDict = {
1255 ">": "Stdout",
1256 ">>": "StdoutAppend",
1257 ">&": "Stderr",
1258 ">>&": "StderrAppend",
1259 "<": "Stdin",
1260 }
1261
1262
1263 _bothSpaceList = {
1264 "=": 1,
1265 "ASSIGNOP": 1,
1266 "COMPOP": 1,
1267 "+": 1,
1268 "-": 1,
1269 "/": 1,
1270 "*": 1,
1271 "//": 1,
1272 }
1273
1274
1275 _trailSpaceList = {
1276 ",": 1,
1277 "REDIR": 1,
1278 "IF": 1,
1279 "WHILE": 1,
1280 }
1281
1282
1283
1284
1285
1286
1287 _stringTypes = { "string": 1,
1288 "char": 1,
1289 "file": 1,
1290 "struct": 1,
1291 "gcur": 1,
1292 "imcur": 1,
1293 "ukey": 1,
1294 "pset": 1,
1295 }
1296
1298 if var.list_flag or _stringTypes.has_key(var.type):
1299 if value is None:
1300 return ""
1301 else:
1302 return str(value)
1303 elif var.type == "int":
1304 if value is None:
1305 return "INDEF"
1306 elif isinstance(value,str) and value[:1] == ")":
1307
1308 return value
1309 else:
1310 return int(value)
1311 elif var.type == "real":
1312 if value is None:
1313 return "INDEF"
1314 elif isinstance(value,str) and value[:1] == ")":
1315
1316 return value
1317 else:
1318 return float(value)
1319 elif var.type == "bool":
1320 if value is None:
1321 return "INDEF"
1322 elif isinstance(value, (int,float)):
1323 if value == 0:
1324 return 'no'
1325 else:
1326 return 'yes'
1327 elif isinstance(value,str):
1328 s = value.lower()
1329 if s == "yes" or s == "y":
1330 s = "yes"
1331 elif s == "no" or s == "n":
1332 s = "'no'"
1333 elif s[:1] == ")":
1334
1335 return value
1336 else:
1337 raise ValueError(
1338 "Illegal value `%s' for boolean variable %s" %
1339 (s, var.name))
1340 return s
1341 else:
1342 try:
1343 return value.bool()
1344 except AttributeError, e:
1345 raise AttributeError(var.name + ':' + str(e))
1346 raise ValueError("unimplemented type `%s'" % (var.type,))
1347
1348
1350
1351 """Check task argument list for errors"""
1352
1361
1362
1364 self.taskname.append(node[0].attr)
1365 self.tasknode.append(node)
1366 self.keywords.append({})
1367
1369 self.taskname.pop()
1370 self.tasknode.pop()
1371 self.keywords.pop()
1372
1374 self.taskname.append(node[0].attr)
1375 self.tasknode.append(node)
1376 self.keywords.append({})
1377
1379 self.taskname.pop()
1380 self.tasknode.pop()
1381 self.keywords.pop()
1382
1384 keyword = node[0].attr
1385 if self.keywords[-1].has_key(keyword):
1386 self.error("Duplicate keyword `%s' in call to %s" %
1387 (keyword, self.taskname[-1]), node)
1388 else:
1389 self.keywords[-1][keyword] = 1
1390
1392 if node[0].type not in ['keyword_arg', 'bool_arg',
1393 'redir_arg', 'non_expr_arg'] and self.keywords[-1]:
1394 self.error("Non-keyword arg after keyword arg in call to %s" %
1395 self.taskname[-1], node)
1396
1398 if self.keywords[-1]:
1399
1400 self.error("Non-keyword (empty) arg after keyword arg in call to %s" %
1401 self.taskname[-1], self.tasknode[-1])
1402
1403
1405 - def __init__(self, ast, vars, filename='', taskObj=None):
1406 self._ecl_iferr_entered = 0
1407 GenericASTTraversal.__init__(self, ast)
1408 self.filename = filename
1409 self.column = 0
1410 self.vars = vars
1411 self.inSwitch = 0
1412 self.caseCount = []
1413
1414
1415
1416
1417
1418 self.printPass = [1]*10
1419 self.code_buffer = cStringIO.StringIO()
1420 self.importDict = {}
1421 self.specialDict = {}
1422 self.pipeOut = []
1423 self.pipeIn = []
1424 self.pipeCount = 0
1425
1426
1427
1428 self.save_incr = []
1429 self.save_indent = []
1430 self.IN_A_WHILE_LOOP = "while"
1431
1432 self._ecl_pyline = 1
1433 self._ecl_clline = None
1434 self._ecl_linemap = {}
1435
1436 if self.vars.proc_name:
1437 self.indent = 1
1438 else:
1439 self.indent = 0
1440
1441 if taskObj and self._ecl_iferr_entered:
1442 self.write("taskObj = iraf.getTask('%s')\n" % taskObj)
1443
1444
1445
1446 self.gotos = GoToAnalyze(ast)
1447
1448
1449
1450 self.errorappend(self.gotos)
1451
1452 self.preorder()
1453 self.write("\n")
1454
1455 self.code = self.code_buffer.getvalue()
1456 self.code_buffer.close()
1457
1458
1459 self.code_buffer = cStringIO.StringIO()
1460 self.writeProcHeader()
1461 header = self.code_buffer.getvalue()
1462 if pyrafglobals._use_ecl:
1463 self.code = self._ecl_linemapping(header) + \
1464 header + \
1465 self.code
1466 else:
1467 self.code = header + self.code
1468 self.code_buffer.close()
1469 del self.code_buffer
1470
1471
1472
1473
1474 self.printerrors()
1475
1476
1478 lines = header.count("\n") + 2
1479 newmap = {}
1480 for key,value in self._ecl_linemap.items():
1481 newmap[ key + lines ] = value
1482 return "_ecl_linemap_" + self.vars.proc_name + " = " + repr(newmap) + "\n\n"
1483
1485 """Increment indentation count"""
1486
1487
1488 self.indent = self.indent+1
1489 if len(self.printPass) <= self.indent:
1490
1491 self.printPass = self.printPass + \
1492 (self.indent+1-len(self.printPass)) * [1]
1493 self.printPass[self.indent] = 1
1494
1496 """Decrement indentation count and write 'pass' if required"""
1497 if self.printPass[self.indent]:
1498 self.writeIndent('pass')
1499 self.indent = self.indent-1
1500 if len(self.save_indent) > 0 and self.save_indent[-1] == self.indent:
1501 del self.save_incr[-1]
1502 del self.save_indent[-1]
1503
1504 - def write(self, s, requireType=None, exprType=None):
1505
1506 """Write string to output code buffer"""
1507
1508 self._ecl_pyline += s.count("\n")
1509 self._ecl_linemap[ self._ecl_pyline ] = self._ecl_clline
1510
1511 if requireType != exprType:
1512
1513 cf = _funcName(requireType, exprType)
1514 if cf is not None:
1515 s = cf + '(' + s + ')'
1516 self.code_buffer.write(s)
1517
1518 self.column = self.column + len(s)
1519
1520 if s[:1] == "\t":
1521 self.column = self.column + 3
1522 if s[-1:] == "\n":
1523 self.column = 0
1524
1526
1527 """Write newline and indent"""
1528
1529 self.write("\n")
1530 for i in range(self.indent):
1531 self.write("\t")
1532 if value: self.write(value)
1533 self.printPass[self.indent] = 0
1534
1536
1537 """Write function definition and other header info"""
1538
1539
1540
1541 printPass = self.printPass[1]
1542
1543
1544 self.indent = 0
1545 self.printPass[0] = 0
1546
1547
1548 noHdr = self.vars.mode == "single" and self.vars.proc_name == ""
1549
1550
1551
1552
1553
1554 if not noHdr:
1555 self.write("from pyraf import iraf")
1556 self.writeIndent("from pyraf.irafpar import makeIrafPar, IrafParList")
1557 self.writeIndent("from pytools.irafglobals import *")
1558 self.writeIndent("from pyraf.pyrafglobals import *")
1559 self.write("\n")
1560
1561 if self.vars.proc_name:
1562
1563
1564 n = len(self.vars.proc_args_list)
1565 namelist = n*[None]
1566 proclist = n*[None]
1567 deflist = n*[None]
1568 for i in range(n):
1569 p = self.vars.proc_args_list[i]
1570 v = self.vars.proc_args_dict[p]
1571 namelist[i] = irafutils.translateName(p)
1572 if _SpecialArgs.has_key(p):
1573
1574 proclist[i] = p + '=' + str(v)
1575 deflist[i] = ''
1576 else:
1577 try:
1578 proclist[i] = v.procLine()
1579 deflist[i] = v.parDefLine()
1580 except AttributeError, e:
1581 raise AttributeError(self.filename + ':' + str(e))
1582
1583 self.writeIndent("def " + self.vars.proc_name + "(")
1584 self.writeChunks(proclist)
1585 self.write("):\n")
1586 self.incrIndent()
1587
1588 self.printPass[self.indent] = printPass
1589 else:
1590 namelist = []
1591 deflist = []
1592
1593
1594 wnewline = 0
1595 if not noHdr:
1596 keylist = self.importDict.keys()
1597 if keylist:
1598 keylist.sort()
1599 self.writeIndent("import ")
1600 self.write(", ".join(keylist))
1601 wnewline = 1
1602
1603 if self.specialDict.has_key("PkgName"):
1604 self.writeIndent("PkgName = iraf.curpack(); "
1605 "PkgBinary = iraf.curPkgbinary()")
1606 wnewline = 1
1607 if wnewline: self.write("\n")
1608
1609
1610 for p in self.vars.local_vars_list[self.vars.local_vars_count:]:
1611 v = self.vars.local_vars_dict[p]
1612 try:
1613 deflist.append(v.parDefLine(local=1))
1614 except AttributeError, e:
1615 raise AttributeError(self.filename + ':' + str(e))
1616
1617 if deflist:
1618
1619 if not noHdr:
1620 self.writeIndent("Vars = IrafParList(" +
1621 `self.vars.proc_name` + ")")
1622 for defargs in deflist:
1623 if defargs:
1624 self.writeIndent("Vars.addParam(makeIrafPar(")
1625 self.writeChunks(defargs)
1626 self.write("))")
1627 self.write("\n")
1628
1629 if pyrafglobals._use_ecl:
1630 self.writeIndent("from pyraf.irafecl import EclState")
1631 self.writeIndent("_ecl = EclState(_ecl_linemap_%s)\n" % self.vars.proc_name)
1632
1633
1634 for label in self.gotos.labels():
1635 self.writeIndent("class GoTo_%s(Exception): pass" % label)
1636
1637
1638 self.decrIndent()
1639
1640
1641
1642
1643
1647
1649 - def n_END(self, node): pass
1651
1652
1653
1654
1655
1657
1658 self.warning("Background execution ignored", node)
1659
1660
1661
1662
1663
1665
1666 s = node.attr
1667 i = s.find('d')
1668 if i>=0:
1669 s = s[:i] + 'e' + s[i+1:]
1670 else:
1671 i = s.find('D')
1672 if i>=0:
1673 s = s[:i] + 'E' + s[i+1:]
1674 self.write(s, node.requireType, node.exprType)
1675
1677
1678 value = node.attr
1679 last = value[-1].lower()
1680 if last == 'b':
1681
1682 self.write('0'+value[:-1], node.requireType, node.exprType)
1683 elif last == 'x':
1684
1685 self.write('0x'+value[:-1], node.requireType, node.exprType)
1686 else:
1687
1688 i=0
1689 for digit in value:
1690 if digit != '0': break
1691 i = i+1
1692 else:
1693
1694 i = i-1
1695 self.write(value[i:], node.requireType, node.exprType)
1696
1698
1699 v = node.attr.split(':')
1700
1701 s = 'iraf.clSexagesimal(' + v[0] + ',' + v[1]
1702 if len(v)>2: s = s + ',' + v[2]
1703 s = s + ')'
1704 self.write(s, node.requireType, node.exprType)
1705
1706 - def n_IDENT(self, node, array_ref=0):
1707 s = irafutils.translateName(node.attr)
1708 if self.vars.has_key(s) and not _SpecialArgs.has_key(s):
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718 self.write('Vars.'+s, node.requireType, node.exprType)
1719 elif '.' in s:
1720
1721
1722
1723
1724
1725
1726 attribs = s.split('.')
1727 ipf = basicpar.isParField(attribs[-1])
1728 if self.vars.has_key(attribs[0]):
1729 attribs.insert(0, 'Vars')
1730 elif ipf and (len(attribs)==2):
1731 attribs.insert(0, 'taskObj')
1732 else:
1733 attribs.insert(0, 'iraf')
1734 if ipf:
1735 attribs[-2] = 'getParObject(' + `attribs[-2]` + ')'
1736 self.write(".".join(attribs),
1737 node.requireType, node.exprType)
1738
1739 else:
1740
1741
1742
1743
1744 if self.vars.mode == "single":
1745 self.write('iraf.cl.'+s, node.requireType, node.exprType)
1746 else:
1747 self.write('taskObj.'+s, node.requireType, node.exprType)
1748
1750
1751
1752 if len(node)>1:
1753 n = self._print_subscript(node[0])
1754 self.write(", ")
1755 else:
1756 n = 0
1757 if node[-1].type == "INTEGER":
1758 self.write(str(int(node[-1])-1))
1759 else:
1760 self.preorder(node[-1])
1761 self.write("-1")
1762 return n+1
1763
1765
1766
1767
1768 cf = _funcName(node.requireType, node.exprType)
1769 if cf: self.write(cf + "(")
1770 self.n_IDENT(node[0], array_ref=1)
1771 self.write("[")
1772 nsub = self._print_subscript(node[2])
1773 self.write("]")
1774 if cf: self.write(")")
1775
1776 s = irafutils.translateName(node[0].attr)
1777 if self.vars.has_key(s):
1778 v = self.vars.get(s)
1779 if nsub < len(v.shape):
1780 self.error("Too few subscripts for array %s" % s, node)
1781 elif nsub > len(v.shape):
1782 self.error("Too many subscripts for array %s" % s, node)
1783 self.prune()
1784
1786 s = irafutils.translateName(node[0].attr,dot=1)
1787 self.write(s)
1788 self.prune()
1789
1792
1794
1795
1796 cf = _funcName(node.requireType, node.exprType)
1797 if cf: self.write(cf + "(")
1798 functionname = node[0].attr
1799 newname = _functionList.get(functionname)
1800 if newname is None:
1801
1802 newname = "iraf." + functionname
1803 self.write(newname + "(")
1804
1805 sargs = self.captureArgs(node[2])
1806 if functionname in ["scan", "fscan", "scanf", "fscanf"]:
1807
1808
1809 sargs = self.modify_scan_args(functionname, sargs)
1810 self.writeChunks(sargs)
1811 self.write(")")
1812 if cf: self.write(")")
1813 self.prune()
1814
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826 sargs = map(repr, sargs)
1827
1828
1829 sargs.insert(0, "locals()")
1830 return sargs
1831
1833
1834 """Handle other tokens"""
1835
1836 if hasattr(node, 'exprType'):
1837 requireType = node.requireType
1838 exprType = node.exprType
1839 else:
1840 requireType = None
1841 exprType = None
1842
1843 if isinstance(node, Token):
1844 s = _translateList.get(node.type)
1845 if s is not None:
1846 self.write(s, requireType, exprType)
1847 elif _trailSpaceList.has_key(node.type):
1848 self.write(`node`, requireType, exprType)
1849 self.write(" ")
1850 elif _bothSpaceList.has_key(node.type):
1851 self.write(" ")
1852 self.write(`node`, requireType, exprType)
1853 self.write(" ")
1854 else:
1855 self.write(`node`, requireType, exprType)
1856 elif requireType != exprType:
1857 cf = _funcName(requireType, exprType)
1858 if cf is not None:
1859 self.write(cf + '(')
1860 for nn in node:
1861 self.preorder(nn)
1862 self.write(')')
1863 self.prune()
1864
1876
1877
1878
1879
1880
1885
1892
1895
1897 if node[0].type == "{":
1898
1899 self.preorder(node[1])
1900 self.prune()
1901 else:
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915 self._ecl_clline = FindLineNumber(node).lineno
1916 self.writeIndent()
1917
1918
1919
1920
1921
1922
1924 self.write("iraf.clOscmd(" + `node[0].attr` + ")")
1925 self.prune()
1926
1936
1938
1939
1940
1941
1942
1943
1944
1945
1946 if len(node) == 3:
1947 stmt = node[2][1]
1948 if stmt.type == "nonnull_stmt" and stmt[0].type == "if_stmt":
1949 self.writeIndent("el")
1950 self.preorder(stmt[0])
1951 self.prune()
1952
1957
1959
1960
1961
1962
1963
1964
1965
1966
1967 if len(node) == 3:
1968 ifkind, guarded_stmt, except_action, else_action = node[0], node[1], node[2], None
1969 elif len(node) == 5:
1970 ifkind, guarded_stmt, except_action, else_action = node[0], node[1], node[4], None
1971 else:
1972 ifkind, guarded_stmt, except_action, else_action = node[0], node[1], node[4], node[7]
1973 if ifkind.type == "IFNOERR":
1974 except_action, else_action = else_action, except_action
1975
1976 self.writeIndent("taskObj._ecl_push_err()\n")
1977
1978 self._ecl_iferr_entered += 1
1979 self.preorder(guarded_stmt)
1980 self._ecl_iferr_entered -= 1
1981
1982 self.write("\n")
1983 self.writeIndent("if taskObj._ecl_pop_err()")
1984
1985 self.preorder(except_action)
1986 if else_action:
1987 self.writeIndent("else")
1988 self.preorder(else_action)
1989 self.prune()
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2010 """we've got a 'while' statement"""
2011
2012
2013 self.save_incr.append(self.IN_A_WHILE_LOOP)
2014
2015
2016 self.save_indent.append(self.indent)
2017
2019
2020
2021
2022
2023
2024
2025
2026
2027 init = node[2]
2028 if init.type == "opt_assign_stmt" and len(init)==0:
2029
2030 self.write("while (")
2031 else:
2032 self.preorder(init)
2033 self.writeIndent("while (")
2034
2035 condition = node[4]
2036 if condition.type == "opt_bool" and len(condition)==0:
2037
2038 self.write("1")
2039 else:
2040 self.preorder(condition)
2041 self.write(")")
2042
2043
2044
2045 self.save_incr.append(node[6])
2046 self.write(":")
2047 self.incrIndent()
2048 for i in range(node[8].label_count):
2049 self.writeIndent("try:")
2050 self.incrIndent()
2051 for subnode in node[8]: self.preorder(subnode)
2052
2053 incr = node[6]
2054 if incr.type == "opt_assign_stmt" and len(incr)==0:
2055
2056 pass
2057 else:
2058 self.writeIndent()
2059 self.preorder(incr)
2060 self.decrIndent()
2061 if len(self.save_incr) > 0:
2062 del(self.save_incr[-1])
2063 self.prune()
2064
2066 if len(self.save_incr) > 0 and \
2067 self.save_incr[-1] != self.IN_A_WHILE_LOOP:
2068
2069 incr = self.save_incr[-1]
2070 if incr.type == "opt_assign_stmt" and len(incr)==0:
2071 pass
2072 else:
2073 self.preorder(incr)
2074 self.writeIndent()
2075 self.write("continue")
2076 self.prune()
2077
2089
2091 self.write("raise GoTo_%s" % irafutils.translateName(node[1].attr))
2092 self.prune()
2093
2103
2105 self.inSwitch = self.inSwitch + 1
2106 self.caseCount.append(0)
2107 self.write("SwitchVal%d = " % (self.inSwitch,))
2108 self.preorder(node[2])
2109 self.preorder(node[4])
2110 self.inSwitch = self.inSwitch - 1
2111 del self.caseCount[-1]
2112 self.prune()
2113
2118
2120 if self.caseCount[-1] == 0:
2121 self.caseCount[-1] = 1
2122 self.writeIndent("if ")
2123 else:
2124 self.writeIndent("elif ")
2125 self.write("SwitchVal%d in [" % (self.inSwitch,))
2126 self.preorder(node[2])
2127 self.write("]")
2128 self.preorder(node[4])
2129 self.prune()
2130
2132 if len(node)>0:
2133 if self.caseCount[-1] == 0:
2134
2135 self.writeIndent("if 1")
2136 else:
2137 self.writeIndent("else")
2138 self.preorder(node[3])
2139 self.prune()
2140
2141
2142
2143
2144
2146 self.pipeCount = self.pipeCount+1
2147 pipename = 'Pipe' + str(self.pipeCount)
2148 self.pipeOut.append(pipename)
2149 self.preorder(node[0])
2150 self.pipeOut.pop()
2151 self.pipeIn.append(pipename)
2152 self.writeIndent()
2153 self.preorder(node[2])
2154 self.pipeIn.pop()
2155 self.pipeCount = self.pipeCount-1
2156 self.prune()
2157
2158
2159
2160
2161
2163 self.errorappend(CheckArgList(node))
2164 taskname = node[0].attr
2165 self.currentTaskname = taskname
2166
2167 if taskname[:1] == '$': taskname = taskname[1:]
2168
2169
2170
2171 self.additionalArguments = []
2172 addsep = ""
2173
2174 if self.pipeIn:
2175
2176 self.additionalArguments.append("Stdin=" + self.pipeIn[-1])
2177 if self.pipeOut:
2178 self.write(self.pipeOut[-1] + " = ")
2179 self.additionalArguments.append("Stdout=1")
2180
2181 newname = _taskList.get(taskname, taskname)
2182 newname = "iraf." + irafutils.translateName(newname)
2183 if taskname in ('task', 'pyexecute'):
2184
2185 self.specialDict['PkgName'] = 1
2186 self.additionalArguments.append("PkgName=PkgName")
2187 self.additionalArguments.append("PkgBinary=PkgBinary")
2188 elif taskname == 'package':
2189
2190 self.specialDict['PkgName'] = 1
2191 self.additionalArguments.append("PkgName=PkgName")
2192 self.additionalArguments.append("PkgBinary=PkgBinary")
2193
2194
2195 if not self.pipeOut: self.write("PkgName, PkgBinary = ")
2196
2197 if self.vars.mode == "single":
2198 self.additionalArguments.append("_save=1")
2199 self.write(newname)
2200 self.preorder(node[1])
2201
2202 if self.pipeIn:
2203
2204 self.writeIndent("del " + self.pipeIn[-1])
2205
2206 if taskname == "clbye" or taskname == "bye":
2207
2208 if self.vars.mode != "single": self.writeIndent("return")
2209 self.prune()
2210
2212
2213 if len(node) == 3:
2214
2215
2216 i = 1
2217 elif len(node) == 1:
2218
2219 i = 0
2220 else:
2221
2222
2223
2224 if node[0].type == "(":
2225
2226 self.warning("Missing closing parenthesis", node)
2227 i = 1
2228 elif node[1].type == ")":
2229
2230 self.warning("Missing opening parenthesis", node)
2231 i = 0
2232
2233
2234
2235 node[i].parent = node
2236
2237
2238 sargs = self.captureArgs(node[i])
2239
2240
2241
2242
2243
2244
2245 if len(sargs) == 1:
2246 s = sargs[0]
2247 if s[:1] == "(" and s[-1:] == ")": sargs[0] = s[1:-1]
2248
2249 if self.currentTaskname in ["scan", "fscan", "scanf", "fscanf"]:
2250
2251
2252 sargs = self.modify_scan_args(self.currentTaskname, sargs)
2253
2254
2255 sargs = sargs + self.additionalArguments
2256 self.additionalArguments = []
2257
2258
2259 self.write("(")
2260 self.writeChunks(sargs)
2261 self.write(")")
2262 self.prune()
2263
2265 """Process the arguments list and return a list of the args"""
2266
2267
2268
2269
2270
2271
2272 arg_buffer = cStringIO.StringIO()
2273 saveColumn = self.column
2274 saveBuffer = self.code_buffer
2275 self.code_buffer = arg_buffer
2276
2277
2278
2279 global _translateList
2280
2281 curComma = _translateList.get(',')
2282 _translateList[','] = ',\255'
2283
2284 self.preorder(node)
2285
2286
2287 if curComma is None:
2288 del _translateList[',']
2289 else:
2290 _translateList[','] = curComma
2291 self.code_buffer = saveBuffer
2292 self.column = saveColumn
2293
2294 args = arg_buffer.getvalue()
2295 arg_buffer.close()
2296
2297
2298 sargs = args.split(',\255')
2299 if sargs[0] == '': del sargs[0]
2300 return sargs
2301
2303
2304 if not arglist: return
2305 maxline = linelength - self.column
2306 newargs = arglist[0]
2307 for arg in arglist[1:]:
2308 if len(newargs)+len(arg)+2>maxline:
2309 self.write(newargs + ',')
2310
2311 newargs = arg
2312 maxline = linelength - self.column
2313 else:
2314 newargs = newargs + ', ' + arg
2315 self.write(newargs)
2316
2318
2319
2320 self.write('None')
2321 self.prune()
2322
2330
2348
2350
2351
2352 assert len(node)==3
2353 self.preorder(node[0])
2354 self.preorder(node[1])
2355
2356 if node[2].type == 'IDENT':
2357 s = irafutils.translateName(node[2].attr)
2358 v = self.vars.get(s)
2359 if v and v.type in ['gcur','imcur']:
2360
2361 self.write('Vars.getParObject("'+s+'")')
2362 self.prune()
2363 return
2364 self.preorder(node[2])
2365 self.prune()
2366
2367 if __name__ == "__main__":
2368
2369 import time
2370
2371 t0 = time.time()
2372
2373
2374
2375 filename = "simple.cl"
2376 lines = open(filename).read()
2377 scanner = clscan.CLScanner()
2378 tokens = scanner.tokenize(lines)
2379 t1 = time.time()
2380
2381
2382 tree = _parser.parse(tokens, fname=filename)
2383 tree.filename = filename
2384 t2 = time.time()
2385
2386
2387
2388 vars = VarList(tree)
2389
2390
2391
2392
2393 TypeCheck(tree, vars, '')
2394
2395
2396
2397 pycode = Tree2Python(tree, vars)
2398
2399 t3 = time.time()
2400
2401 print "Scan:", t1-t0, "sec, Parse:", t2-t1, "sec"
2402 print "CodeGen:", t3-t2, "sec"
2403