GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
pt-pr-code.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2013 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #include <cctype>
28 
29 #include <iostream>
30 
31 #include "comment-list.h"
32 #include "error.h"
33 #include "ov-usr-fcn.h"
34 #include "pr-output.h"
35 #include "pt-all.h"
36 
37 void
39 {
40  indent ();
41 
42  print_parens (afh, "(");
43 
44  os << "@(";
45 
46  tree_parameter_list *param_list = afh.parameter_list ();
47 
48  if (param_list)
49  param_list->accept (*this);
50 
51  os << ") ";
52 
53  print_fcn_handle_body (afh.body ());
54 
55  print_parens (afh, ")");
56 }
57 
58 void
60 {
62 
63  while (p != lst.end ())
64  {
65  tree_expression *elt = *p++;
66 
67  if (elt)
68  {
69  elt->accept (*this);
70 
71  if (p != lst.end ())
72  os << ", ";
73  }
74  }
75 }
76 
77 void
79 {
80  indent ();
81 
82  print_parens (expr, "(");
83 
84  tree_expression *op1 = expr.lhs ();
85 
86  if (op1)
87  op1->accept (*this);
88 
89  os << " " << expr.oper () << " ";
90 
91  tree_expression *op2 = expr.rhs ();
92 
93  if (op2)
94  op2->accept (*this);
95 
96  print_parens (expr, ")");
97 }
98 
99 void
101 {
102  indent ();
103 
104  os << "break";
105 }
106 
107 void
109 {
110  indent ();
111 
112  print_parens (expr, "(");
113 
114  tree_expression *op1 = expr.base ();
115 
116  if (op1)
117  op1->accept (*this);
118 
119  // Stupid syntax.
120 
121  tree_expression *op3 = expr.increment ();
122 
123  if (op3)
124  {
125  os << ":";
126  op3->accept (*this);
127  }
128 
129  tree_expression *op2 = expr.limit ();
130 
131  if (op2)
132  {
133  os << ":";
134  op2->accept (*this);
135  }
136 
137  print_parens (expr, ")");
138 }
139 
140 void
142 {
143  indent ();
144 
145  os << "continue";
146 }
147 
148 void
150 {
151  indent ();
152 
153  os << cmd.name () << " ";
154 
155  tree_decl_init_list *init_list = cmd.initializer_list ();
156 
157  if (init_list)
158  init_list->accept (*this);
159 }
160 
161 void
163 {
164  do_decl_command (cmd);
165 }
166 
167 void
169 {
170  do_decl_command (cmd);
171 }
172 
173 void
175 {
176  tree_identifier *id = cmd.ident ();
177 
178  if (id)
179  id->accept (*this);
180 
181  tree_expression *expr = cmd.expression ();
182 
183  if (expr)
184  {
185  os << " = ";
186 
187  expr->accept (*this);
188  }
189 }
190 
191 void
193 {
195 
196  while (p != lst.end ())
197  {
198  tree_decl_elt *elt = *p++;
199 
200  if (elt)
201  {
202  elt->accept (*this);
203 
204  if (p != lst.end ())
205  os << ", ";
206  }
207  }
208 }
209 
210 void
212 {
214 
215  indent ();
216 
217  os << (cmd.in_parallel () ? "parfor " : "for ");
218 
219  tree_expression *lhs = cmd.left_hand_side ();
220 
221  tree_expression *maxproc = cmd.maxproc_expr ();
222 
223  if (maxproc)
224  os << "(";
225 
226  if (lhs)
227  lhs->accept (*this);
228 
229  os << " = ";
230 
231  tree_expression *expr = cmd.control_expr ();
232 
233  if (expr)
234  expr->accept (*this);
235 
236  if (maxproc)
237  {
238  os << ", ";
239  maxproc->accept (*this);
240  os << ")";
241  }
242 
243  newline ();
244 
245  tree_statement_list *list = cmd.body ();
246 
247  if (list)
248  {
250 
251  list->accept (*this);
252 
254  }
255 
257 
258  indent ();
259 
260  os << (cmd.in_parallel () ? "endparfor" : "endfor");
261 }
262 
263 void
265 {
267 
268  indent ();
269 
270  os << "for [";
271  nesting.push ('[');
272 
273  tree_argument_list *lhs = cmd.left_hand_side ();
274 
275  if (lhs)
276  lhs->accept (*this);
277 
278  nesting.pop ();
279  os << "] = ";
280 
281  tree_expression *expr = cmd.control_expr ();
282 
283  if (expr)
284  expr->accept (*this);
285 
286  newline ();
287 
288  tree_statement_list *list = cmd.body ();
289 
290  if (list)
291  {
293 
294  list->accept (*this);
295 
297  }
298 
300 
301  indent ();
302 
303  os << "endfor";
304 }
305 
306 void
308 {
309  reset ();
310 
311  tree_statement_list *cmd_list = fcn.body ();
312 
313  if (cmd_list)
314  cmd_list->accept (*this);
315 }
316 
317 void
319 {
320  reset ();
321 
323 
324  tree_statement_list *cmd_list = fcn.body ();
325 
326  if (cmd_list)
327  {
329 
330  cmd_list->accept (*this);
331 
333  }
334 
336 }
337 
338 void
340 {
341  octave_comment_list *leading_comment = fcn.leading_comment ();
342 
343  if (leading_comment)
344  {
345  print_comment_list (leading_comment);
346  newline ();
347  }
348 
349  indent ();
350 
351  os << "function ";
352 
353  tree_parameter_list *ret_list = fcn.return_list ();
354 
355  if (ret_list)
356  {
357  bool takes_var_return = fcn.takes_var_return ();
358 
359  int len = ret_list->length ();
360 
361  if (len > 1 || takes_var_return)
362  {
363  os << "[";
364  nesting.push ('[');
365  }
366 
367  ret_list->accept (*this);
368 
369  if (takes_var_return)
370  {
371  if (len > 0)
372  os << ", ";
373 
374  os << "varargout";
375  }
376 
377  if (len > 1 || takes_var_return)
378  {
379  nesting.pop ();
380  os << "]";
381  }
382 
383  os << " = ";
384  }
385 
386  std::string fcn_name = fcn.name ();
387 
388  os << (fcn_name.empty () ? std::string ("(empty)") : fcn_name) << " ";
389 
390  tree_parameter_list *param_list = fcn.parameter_list ();
391 
392  if (param_list)
393  {
394  bool takes_varargs = fcn.takes_varargs ();
395 
396  int len = param_list->length ();
397 
398  if (len > 0 || takes_varargs)
399  {
400  os << "(";
401  nesting.push ('(');
402  }
403 
404  param_list->accept (*this);
405 
406  if (takes_varargs)
407  {
408  if (len > 0)
409  os << ", ";
410 
411  os << "varargin";
412  }
413 
414  if (len > 0 || takes_varargs)
415  {
416  nesting.pop ();
417  os << ")";
418  newline ();
419  }
420  }
421  else
422  {
423  os << "()";
424  newline ();
425  }
426 }
427 
428 void
430 {
432 
433  newline ();
434 }
435 
436 void
438 {
439  indent ();
440 
441  octave_value fcn = fdef.function ();
442 
443  octave_function *f = fcn.function_value ();
444 
445  if (f)
446  f->accept (*this);
447 }
448 
449 void
451 {
452  indent ();
453 
454  print_parens (id, "(");
455 
456  std::string nm = id.name ();
457  os << (nm.empty () ? std::string ("(empty)") : nm);
458 
459  print_parens (id, ")");
460 }
461 
462 void
464 {
465  tree_expression *expr = cmd.condition ();
466 
467  if (expr)
468  expr->accept (*this);
469 
470  newline ();
471 
472  tree_statement_list *list = cmd.commands ();
473 
474  if (list)
475  {
477 
478  list->accept (*this);
479 
481  }
482 }
483 
484 void
486 {
488 
489  indent ();
490 
491  os << "if ";
492 
493  tree_if_command_list *list = cmd.cmd_list ();
494 
495  if (list)
496  list->accept (*this);
497 
499 
500  indent ();
501 
502  os << "endif";
503 }
504 
505 void
507 {
509 
510  bool first_elt = true;
511 
512  while (p != lst.end ())
513  {
514  tree_if_clause *elt = *p++;
515 
516  if (elt)
517  {
518  if (! first_elt)
519  {
521 
522  indent ();
523 
524  if (elt->is_else_clause ())
525  os << "else";
526  else
527  os << "elseif ";
528  }
529 
530  elt->accept (*this);
531  }
532 
533  first_elt = false;
534  }
535 }
536 
537 void
539 {
540  indent ();
541 
542  print_parens (expr, "(");
543 
544  tree_expression *e = expr.expression ();
545 
546  if (e)
547  e->accept (*this);
548 
549  std::list<tree_argument_list *> arg_lists = expr.arg_lists ();
550  std::string type_tags = expr.type_tags ();
551  std::list<string_vector> arg_names = expr.arg_names ();
552 
553  int n = type_tags.length ();
554 
555  std::list<tree_argument_list *>::iterator p_arg_lists = arg_lists.begin ();
556  std::list<string_vector>::iterator p_arg_names = arg_names.begin ();
557 
558  for (int i = 0; i < n; i++)
559  {
560  switch (type_tags[i])
561  {
562  case '(':
563  {
564  char nc = nesting.top ();
565  if ((nc == '[' || nc == '{') && expr.paren_count () == 0)
566  os << "(";
567  else
568  os << " (";
569  nesting.push ('(');
570 
571  tree_argument_list *l = *p_arg_lists;
572  if (l)
573  l->accept (*this);
574 
575  nesting.pop ();
576  os << ")";
577  }
578  break;
579 
580  case '{':
581  {
582  char nc = nesting.top ();
583  if ((nc == '[' || nc == '{') && expr.paren_count () == 0)
584  os << "{";
585  else
586  os << " {";
587  // We only care about whitespace inside [] and {} when we
588  // are defining matrix and cell objects, not when indexing.
589  nesting.push ('(');
590 
591  tree_argument_list *l = *p_arg_lists;
592  if (l)
593  l->accept (*this);
594 
595  nesting.pop ();
596  os << "}";
597  }
598  break;
599 
600  case '.':
601  {
602  string_vector nm = *p_arg_names;
603  assert (nm.length () == 1);
604  os << "." << nm(0);
605  }
606  break;
607 
608  default:
609  panic_impossible ();
610  }
611 
612  p_arg_lists++;
613  p_arg_names++;
614  }
615 
616  print_parens (expr, ")");
617 }
618 
619 void
621 {
622  indent ();
623 
624  print_parens (lst, "(");
625 
626  os << "[";
627  nesting.push ('[');
628 
629  tree_matrix::iterator p = lst.begin ();
630 
631  while (p != lst.end ())
632  {
633  tree_argument_list *elt = *p++;
634 
635  if (elt)
636  {
637  elt->accept (*this);
638 
639  if (p != lst.end ())
640  os << "; ";
641  }
642  }
643 
644  nesting.pop ();
645  os << "]";
646 
647  print_parens (lst, ")");
648 }
649 
650 void
652 {
653  indent ();
654 
655  print_parens (lst, "(");
656 
657  os << "{";
658  nesting.push ('{');
659 
660  tree_cell::iterator p = lst.begin ();
661 
662  while (p != lst.end ())
663  {
664  tree_argument_list *elt = *p++;
665 
666  if (elt)
667  {
668  elt->accept (*this);
669 
670  if (p != lst.end ())
671  os << "; ";
672  }
673  }
674 
675  nesting.pop ();
676  os << "}";
677 
678  print_parens (lst, ")");
679 }
680 
681 void
683 {
684  indent ();
685 
686  print_parens (expr, "(");
687 
688  tree_argument_list *lhs = expr.left_hand_side ();
689 
690  if (lhs)
691  {
692  int len = lhs->length ();
693 
694  if (len > 1)
695  {
696  os << "[";
697  nesting.push ('[');
698  }
699 
700  lhs->accept (*this);
701 
702  if (len > 1)
703  {
704  nesting.pop ();
705  os << "]";
706  }
707  }
708 
709  os << " " << expr.oper () << " ";
710 
711  tree_expression *rhs = expr.right_hand_side ();
712 
713  if (rhs)
714  rhs->accept (*this);
715 
716  print_parens (expr, ")");
717 }
718 
719 void
721 {
722  indent ();
723 
724  os << cmd.original_command ();
725 }
726 
727 void
729 {
730  indent ();
731 
732  print_parens (val, "(");
733 
734  val.print_raw (os, true, print_original_text);
735 
736  print_parens (val, ")");
737 }
738 
739 void
741 {
742  indent ();
743 
744  print_parens (fh, "(");
745 
746  fh.print_raw (os, true, print_original_text);
747 
748  print_parens (fh, ")");
749 }
750 
751 void
753 {
755 
756  while (p != lst.end ())
757  {
758  tree_decl_elt *elt = *p++;
759 
760  if (elt)
761  {
762  elt->accept (*this);
763 
764  if (p != lst.end ())
765  os << ", ";
766  }
767  }
768 }
769 
770 void
772 {
773  indent ();
774 
775  print_parens (expr, "(");
776 
777  tree_expression *e = expr.operand ();
778 
779  if (e)
780  e->accept (*this);
781 
782  os << expr.oper ();
783 
784  print_parens (expr, ")");
785 }
786 
787 void
789 {
790  indent ();
791 
792  print_parens (expr, "(");
793 
794  os << expr.oper ();
795 
796  tree_expression *e = expr.operand ();
797 
798  if (e)
799  e->accept (*this);
800 
801  print_parens (expr, ")");
802 }
803 
804 void
806 {
807  indent ();
808 
809  os << "return";
810 }
811 
812 void
814 {
816 
817  while (p != lst.end ())
818  {
819  tree_index_expression *elt = *p++;
820 
821  if (elt)
822  {
823  elt->accept (*this);
824 
825  if (p != lst.end ())
826  os << ", ";
827  }
828  }
829 }
830 
831 void
833 {
834  indent ();
835 
836  print_parens (expr, "(");
837 
838  tree_expression *lhs = expr.left_hand_side ();
839 
840  if (lhs)
841  lhs->accept (*this);
842 
843  os << " " << expr.oper () << " ";
844 
845  tree_expression *rhs = expr.right_hand_side ();
846 
847  if (rhs)
848  rhs->accept (*this);
849 
850  print_parens (expr, ")");
851 }
852 
853 void
855 {
857 
858  tree_command *cmd = stmt.command ();
859 
860  if (cmd)
861  {
862  cmd->accept (*this);
863 
864  if (! stmt.print_result ())
865  {
866  os << ";";
867  newline (" ");
868  }
869  else
870  newline ();
871  }
872  else
873  {
874  tree_expression *expr = stmt.expression ();
875 
876  if (expr)
877  {
878  expr->accept (*this);
879 
880  if (! stmt.print_result ())
881  {
882  os << ";";
883  newline (" ");
884  }
885  else
886  newline ();
887  }
888  }
889 }
890 
891 void
893 {
894  for (tree_statement_list::iterator p = lst.begin (); p != lst.end (); p++)
895  {
896  tree_statement *elt = *p;
897 
898  if (elt)
899  elt->accept (*this);
900  }
901 }
902 
903 void
905 {
907 
908  indent ();
909 
910  if (cs.is_default_case ())
911  os << "otherwise";
912  else
913  os << "case ";
914 
915  tree_expression *label = cs.case_label ();
916 
917  if (label)
918  label->accept (*this);
919 
920  newline ();
921 
922  tree_statement_list *list = cs.commands ();
923 
924  if (list)
925  {
927 
928  list->accept (*this);
929 
930  newline ();
931 
933  }
934 }
935 
936 void
938 {
940 
941  while (p != lst.end ())
942  {
943  tree_switch_case *elt = *p++;
944 
945  if (elt)
946  elt->accept (*this);
947  }
948 }
949 
950 void
952 {
954 
955  indent ();
956 
957  os << "switch ";
958 
959  tree_expression *expr = cmd.switch_value ();
960 
961  if (expr)
962  expr->accept (*this);
963 
964  newline ();
965 
966  tree_switch_case_list *list = cmd.case_list ();
967 
968  if (list)
969  {
971 
972  list->accept (*this);
973 
975  }
976 
978 
979  indent ();
980 
981  os << "endswitch";
982 }
983 
984 void
986 {
988 
989  indent ();
990 
991  os << "try";
992 
993  newline ();
994 
995  tree_statement_list *try_code = cmd.body ();
996  tree_identifier *expr_id = cmd.identifier ();
997 
998  if (try_code)
999  {
1001 
1002  try_code->accept (*this);
1003 
1005  }
1006 
1008 
1009  indent ();
1010 
1011  os << "catch";
1012 
1013  if (expr_id)
1014  {
1015  os << " ";
1016  expr_id->accept (*this);
1017  }
1018 
1019  newline ();
1020 
1021  tree_statement_list *catch_code = cmd.cleanup ();
1022 
1023  if (catch_code)
1024  {
1026 
1027  catch_code->accept (*this);
1028 
1030  }
1031 
1033 
1034  indent ();
1035 
1036  os << "end_try_catch";
1037 }
1038 
1039 void
1041 {
1043 
1044  indent ();
1045 
1046  os << "unwind_protect";
1047 
1048  newline ();
1049 
1050  tree_statement_list *unwind_protect_code = cmd.body ();
1051 
1052  if (unwind_protect_code)
1053  {
1055 
1056  unwind_protect_code->accept (*this);
1057 
1059  }
1060 
1062 
1063  indent ();
1064 
1065  os << "unwind_protect_cleanup";
1066 
1067  newline ();
1068 
1069  tree_statement_list *cleanup_code = cmd.cleanup ();
1070 
1071  if (cleanup_code)
1072  {
1074 
1075  cleanup_code->accept (*this);
1076 
1078  }
1079 
1081 
1082  indent ();
1083 
1084  os << "end_unwind_protect";
1085 }
1086 
1087 void
1089 {
1091 
1092  indent ();
1093 
1094  os << "while ";
1095 
1096  tree_expression *expr = cmd.condition ();
1097 
1098  if (expr)
1099  expr->accept (*this);
1100 
1101  newline ();
1102 
1103  tree_statement_list *list = cmd.body ();
1104 
1105  if (list)
1106  {
1108 
1109  list->accept (*this);
1110 
1112  }
1113 
1115 
1116  indent ();
1117 
1118  os << "endwhile";
1119 }
1120 
1121 void
1123 {
1125 
1126  indent ();
1127 
1128  os << "do";
1129 
1130  newline ();
1131 
1132  tree_statement_list *list = cmd.body ();
1133 
1134  if (list)
1135  {
1137 
1138  list->accept (*this);
1139 
1141  }
1142 
1144 
1145  indent ();
1146 
1147  os << "until";
1148 
1149  tree_expression *expr = cmd.condition ();
1150 
1151  if (expr)
1152  expr->accept (*this);
1153 
1154  newline ();
1155 }
1156 
1157 void
1159 {
1160  if (b)
1161  {
1162  assert (b->length () == 1);
1163 
1164  tree_statement *s = b->front ();
1165 
1166  if (s)
1167  {
1168  if (s->is_expression ())
1169  {
1170  tree_expression *e = s->expression ();
1171 
1172  if (e)
1173  {
1175  e->accept (*this);
1177  }
1178  }
1179  else
1180  {
1181  tree_command *c = s->command ();
1182 
1184  c->accept (*this);
1186  }
1187  }
1188  }
1189 }
1190 
1191 // Each print_code() function should call this before printing
1192 // anything.
1193 //
1194 // This doesn't need to be fast, but isn't there a better way?
1195 
1196 void
1198 {
1199  assert (curr_print_indent_level >= 0);
1200 
1201  if (beginning_of_line)
1202  {
1203  os << prefix;
1204 
1205  for (int i = 0; i < curr_print_indent_level; i++)
1206  os << " ";
1207 
1208  beginning_of_line = false;
1209  }
1210 }
1211 
1212 // All print_code() functions should use this to print new lines.
1213 
1214 void
1215 tree_print_code::newline (const char *alt_txt)
1216 {
1217  if (suppress_newlines)
1218  os << alt_txt;
1219  else
1220  {
1221  os << "\n";
1222 
1223  beginning_of_line = true;
1224  }
1225 }
1226 
1227 // For ressetting print_code state.
1228 
1229 void
1231 {
1232  beginning_of_line = true;
1234  while (nesting.top () != 'n')
1235  nesting.pop ();
1236 }
1237 
1238 void
1239 tree_print_code::print_parens (const tree_expression& expr, const char *txt)
1240 {
1241  int n = expr.paren_count ();
1242 
1243  for (int i = 0; i < n; i++)
1244  os << txt;
1245 }
1246 
1247 void
1249 {
1250  bool printed_something = false;
1251 
1252  bool prev_char_was_newline = false;
1253 
1254  std::string comment = elt.text ();
1255 
1256  size_t len = comment.length ();
1257 
1258  size_t i = 0;
1259 
1260  while (i < len && comment[i++] == '\n')
1261  ; /* Skip leading new lines. */
1262  i--;
1263 
1264  while (i < len)
1265  {
1266  char c = comment[i++];
1267 
1268  if (c == '\n')
1269  {
1270  if (prev_char_was_newline)
1271  os << "##";
1272 
1273  newline ();
1274 
1275  prev_char_was_newline = true;
1276  }
1277  else
1278  {
1279  if (beginning_of_line)
1280  {
1281  printed_something = true;
1282 
1283  indent ();
1284 
1285  os << "##";
1286 
1287  if (! (isspace (c) || c == '!'))
1288  os << " ";
1289  }
1290 
1291  os << static_cast<char> (c);
1292 
1293  prev_char_was_newline = false;
1294  }
1295  }
1296 
1297  if (printed_something && ! beginning_of_line)
1298  newline ();
1299 }
1300 
1301 void
1303 {
1304  if (comment_list)
1305  {
1306  octave_comment_list::iterator p = comment_list->begin ();
1307 
1308  while (p != comment_list->end ())
1309  {
1310  octave_comment_elt elt = *p++;
1311 
1312  print_comment_elt (elt);
1313 
1314  if (p != comment_list->end ())
1315  newline ();
1316  }
1317  }
1318 }
1319 
1320 void
1322 {
1324 
1325  print_comment_list (comment_list);
1326 
1328 }