Skip to content

Commit 106fcab

Browse files
committed
handling do-while, started work on list comprehensions, fixed some bugs
1 parent 78b927e commit 106fcab

File tree

4 files changed

+111
-35
lines changed

4 files changed

+111
-35
lines changed

open_fortran_parser/ast_transformer.py

Lines changed: 63 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -282,8 +282,8 @@ def _declaration_include(self, node: ET.Element):
282282
def _loop(self, node: ET.Element):
283283
if node.attrib['type'] == 'do':
284284
return self._loop_do(node)
285-
#elif node.attrib['type'] == 'do-while':
286-
# return self._loop_do_while(node)
285+
elif node.attrib['type'] == 'do-while':
286+
return self._loop_do_while(node)
287287
elif node.attrib['type'] == 'forall':
288288
return self._loop_forall(node)
289289
else:
@@ -297,7 +297,12 @@ def _loop_do(self, node: ET.Element) -> typed_ast3.For:
297297
return typed_ast3.For(target=target, iter=iter_, body=body, orelse=[])
298298

299299
def _loop_do_while(self, node: ET.Element) -> typed_ast3.While:
300-
pass
300+
header_node = node.find('./header')
301+
header = self.transform_all_subnodes(header_node, warn=False)
302+
assert len(header) == 1
303+
condition = header[0]
304+
body = self.transform_all_subnodes(node.find('./body'), ignored={'block'})
305+
return typed_ast3.While(test=condition, body=body, orelse=[])
301306

302307
def _loop_forall(self, node: ET.Element) -> typed_ast3.For:
303308
index_variables = node.find('./header/index-variables')
@@ -508,7 +513,7 @@ def _operation_multiary(
508513
operators_and_operands = self.transform_all_subnodes(
509514
node, skip_empty=True, ignored={
510515
'add-operand__add-op', 'add-operand', 'mult-operand__mult-op', 'mult-operand',
511-
'primary'})
516+
'primary', 'level-3-expr'})
512517
assert isinstance(operators_and_operands, list), operators_and_operands
513518
assert len(operators_and_operands) % 2 == 1, operators_and_operands
514519

@@ -653,42 +658,76 @@ def _operator(
653658
}[node.attrib['operator'].lower()]
654659

655660
def _array_constructor(self, node: ET.Element) -> typed_ast3.ListComp:
656-
values = node.findall('./value')
657-
if len(values) != 2:
658-
raise NotImplementedError('not implemented handling of:\n{}'.format(ET.tostring(node).decode().rstrip()))
659-
value = values[0]
660-
sub_values = value.find('./array-constructor-values')
661-
header_node = value.find('./header')
662-
header = self.transform_all_subnodes(header_node, warn=False)
661+
value_nodes = node.findall('./value')
662+
values = []
663+
for value_node in value_nodes:
664+
value = self.transform_all_subnodes(value_node, warn=False)
665+
if not value:
666+
continue
667+
assert len(value) == 1
668+
values.append(value[0])
669+
670+
if len(values) != 1:
671+
raise NotImplementedError(
672+
'not implemented handling of {} in:\n{}'
673+
.format(values, ET.tostring(node).decode().rstrip()))
674+
675+
header_node = node.find('./header')
676+
header = self.transform_all_subnodes(header_node, warn=False, ignored={'ac-implied-do-control'})
663677
assert len(header) == 1
664678
comp_target, comp_iter = header[0]
665679
return typed_ast3.ListComp(
666-
elt=typed_ast3.Call(
667-
func=typed_ast3.Name(id='do_nothing', ctx=typed_ast3.Load()),
668-
args=[], keywords=[], starargs=None, kwargs=None),
680+
elt=values[0],
669681
generators=[
670682
typed_ast3.comprehension(target=comp_target, iter=comp_iter, ifs=[], is_async=0)])
671683

672-
# "[ord(c) for line in file for c in line]"
673-
#_(elt=Call(func=Name(id='ord', ctx=Load()), args=[
674-
# Name(id='c', ctx=Load()),
675-
#], keywords=[], starargs=None, kwargs=None), generators=[
676-
# comprehension(target=Name(id='line', ctx=Store()), iter=Name(id='file', ctx=Load()), ifs=[], is_async=0),
677-
# comprehension(target=Name(id='c', ctx=Store()), iter=Name(id='line', ctx=Load()), ifs=[], is_async=0),
678-
#])
684+
def _array_constructor_values(self, node: ET.Element) -> typed_ast3.List:
685+
value_nodes = node.findall('./value')
686+
values = []
687+
for value_node in value_nodes:
688+
value = self.transform_all_subnodes(value_node, warn=False)
689+
if not value:
690+
continue
691+
assert len(value) == 1
692+
values.append(value[0])
693+
694+
return typed_ast3.List(elts=values, ctx=typed_ast3.Load())
679695

680-
def _dimension(self, node: ET.Element) -> t.Union[typed_ast3.Num, typed_ast3.Index]:
696+
def _dimension(self, node: ET.Element) -> t.Union[typed_ast3.Index, typed_ast3.Slice]:
681697
dim_type = node.attrib['type']
682698
if dim_type == 'simple':
683699
values = self.transform_all_subnodes(node, ignored={'array-spec-element'})
684700
if len(values) != 1:
685701
_LOG.error('simple dimension should have exactly one value, but it has %i', len(values))
686702
return typed_ast3.Index(value=values[0])
703+
elif dim_type == 'range':
704+
lower_bound = node.find('./lower-bound')
705+
upper_bound = node.find('./upper-bound')
706+
step = node.find('./step')
707+
#range_args = []
708+
if lower_bound is not None:
709+
args = self.transform_all_subnodes(lower_bound)
710+
assert len(args) == 1, args
711+
#range_args.append(args[0])
712+
lower_bound = args[0]
713+
if upper_bound is not None:
714+
args = self.transform_all_subnodes(upper_bound)
715+
assert len(args) == 1, args
716+
#range_args.append(typed_ast3.BinOp(
717+
# left=args[0], op=typed_ast3.Add(), right=typed_ast3.Num(n=1)))
718+
upper_bound = args[0]
719+
if step is not None:
720+
args = self.transform_all_subnodes(step)
721+
assert len(args) == 1, args
722+
#range_args.append(args[0])
723+
step = args[0]
724+
return typed_ast3.Slice(lower=lower_bound, upper=upper_bound, step=step)
687725
elif dim_type == 'assumed-shape':
688726
return typed_ast3.Slice(lower=None, upper=None, step=None)
689727
else:
690-
_LOG.warning('%s', ET.tostring(node).decode().rstrip())
691-
raise NotImplementedError('dimension type "{}" not supported'.format(dim_type))
728+
raise NotImplementedError(
729+
'dimension type "{}" not supported in:\n{}'
730+
.format(dim_type, ET.tostring(node).decode().rstrip()))
692731

693732
_basic_types = {
694733
('logical', None): 'bool',

src/fortran/ofp/XMLPrinter.java

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,6 @@ public void array_constructor() {
534534
context = contextNode(-1); // temporarily reopen previously-closed context
535535
if (verbosity >= 100)
536536
super.array_constructor();
537-
contextRename("array-constructor-values", "array-constructor");
538537
contextClose(); // re-close previously closed context
539538
}
540539

@@ -561,11 +560,30 @@ public void ac_value_list__begin() {
561560

562561
public void ac_value_list(int count) {
563562
contextClose("value");
564-
contextCloseAllInner("array-constructor-values");
563+
contextCloseAllInner("array-constructor-values", "array-constructor");
565564
setAttribute("count", count);
566565
if (verbosity >= 100)
567566
super.ac_value_list(count);
568-
contextClose("array-constructor-values");
567+
contextClose("array-constructor-values", "array-constructor");
568+
}
569+
570+
public void ac_implied_do() {
571+
Element value = context;
572+
contextClose();
573+
Element innerContext = context;
574+
contextClose("value");
575+
innerContext.removeChild(value);
576+
context.appendChild(value);
577+
super.ac_implied_do();
578+
contextRename("array-constructor-values", "array-constructor");
579+
contextOpen("value");
580+
// System.err.println("well...");
581+
// cleanUpAfterError();
582+
}
583+
584+
public void ac_implied_do_control(boolean hasStride) {
585+
contextClose("index-variable");
586+
super.ac_implied_do_control(hasStride);
569587
}
570588

571589
public void type_declaration_stmt(Token label, int numAttributes, Token eos) {
@@ -1395,8 +1413,16 @@ public void and_operand__not_op(boolean hasNotOp) {
13951413
}
13961414

13971415
public void or_operand(int numOrOps) {
1398-
if (numOrOps > 0)
1416+
if (numOrOps > 0) {
1417+
if (!context.getTagName().equals("operand")) {
1418+
Element previousContext = contextNode(-1);
1419+
Element outerContext = context;
1420+
contextOpen("operand");
1421+
outerContext.removeChild(previousContext);
1422+
context.appendChild(previousContext);
1423+
}
13991424
contextClose("operand");
1425+
}
14001426
if (verbosity >= 100)
14011427
super.or_operand(numOrOps);
14021428
if (numOrOps > 0)
@@ -1737,8 +1763,9 @@ public void block_do_construct() {
17371763
}
17381764

17391765
public void do_stmt(Token label, Token id, Token doKeyword, Token digitString, Token eos, boolean hasLoopControl) {
1740-
if (context.getTagName() != "header") {
1741-
contextOpen("loop");
1766+
if (!context.getTagName().equals("header")) {
1767+
if (!context.getTagName().equals("loop"))
1768+
contextOpen("loop");
17421769
contextOpen("header");
17431770
}
17441771
contextClose("header");
@@ -1761,11 +1788,8 @@ public void label_do_stmt(Token label, Token id, Token doKeyword, Token digitStr
17611788
public void loop_control(Token whileKeyword, int doConstructType, boolean hasOptExpr) {
17621789
if (!context.getTagName().equals("statement"))
17631790
contextClose("index-variable");
1764-
else {
1791+
else
17651792
contextRename("statement", "loop");
1766-
// setAttribute("type", "do");
1767-
}
1768-
super.loop_control(whileKeyword, doConstructType, hasOptExpr);
17691793
String loopType = "";
17701794
switch (doConstructType) {
17711795
case 1700:
@@ -1775,11 +1799,18 @@ public void loop_control(Token whileKeyword, int doConstructType, boolean hasOpt
17751799
loopType = "do";
17761800
break;
17771801
case 1702:
1802+
Element outerContext = context;
1803+
Element node = contextNode(-1);
1804+
contextOpen("header");
1805+
outerContext.removeChild(node);
1806+
context.appendChild(node);
1807+
contextClose("header");
17781808
loopType = "do-while";
17791809
break;
17801810
default:
17811811
throw new IllegalArgumentException(Integer.toString(doConstructType));
17821812
}
1813+
super.loop_control(whileKeyword, doConstructType, hasOptExpr);
17831814
setAttribute("type", loopType, "loop");
17841815
}
17851816

test/examples/empty.f

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
program empty
3+
4+
implicit none
5+
6+
end program empty

test/test_ofc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
_HERE = pathlib.Path(__file__).resolve().parent
1212

13-
INPUT_PATHS = list(_HERE.joinpath('examples').glob('**/*.*'))
13+
INPUT_PATHS = [_HERE.joinpath('examples', _) for _ in ['empty.f']]
1414
OUTPUT_PATHS = [None] # [pathlib.Path('/tmp/out.f'), None]
1515
INDENTS = (4,) # (0, 4, 8)
1616
FORMS = (None,) # (CodeForm.Fixed, CodeForm.Free, None)

0 commit comments

Comments
 (0)