OpenCores
URL https://opencores.org/ocsvn/tcp_socket/tcp_socket/trunk

Subversion Repositories tcp_socket

[/] [tcp_socket/] [trunk/] [chips2/] [chips/] [compiler/] [parser.py,cover] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jondawson
> __author__ = "Jon Dawson"
2
> __copyright__ = "Copyright (C) 2012, Jonathan P Dawson"
3
> __version__ = "0.1"
4
 
5
> from parse_tree import *
6
> from tokens import Tokens
7
> from allocator import Allocator
8
 
9
> def optimise_if(if_statement):
10
>     try:
11
>         if value(if_statement.expression):
12
>             return if_statement.true_statement
13
>         elif if_statement.false_statement:
14
>             return if_statement.false_statement
15
>         else:
16
>             null_instruction = Block()
17
>             null_instruction.statements = []
18
>             return null_instruction
19
>     except NotConstant:
20
>         return if_statement
21
 
22
> class Parser:
23
 
24
>     """Turn the C input file into a tree of expressions and statements."""
25
 
26
>     def __init__(self, input_file, reuse):
27
>         self.scope = {}
28
>         self.function = None
29
>         self.loop = None
30
>         self.tokens = Tokens(input_file)
31
>         self.allocator = Allocator(reuse)
32
>         self.structs = []
33
 
34
>     def parse_process(self):
35
>         process = Process()
36
>         process.allocator = self.allocator
37
>         process.inputs = []
38
>         process.outputs = []
39
>         process.functions = []
40
>         while not self.tokens.end():
41
>             if self.tokens.peek() == "struct":
42
>                 self.parse_define_struct()
43
>             elif self.tokens.peek() == "typedef":
44
>                 self.parse_typedef_struct()
45
>             else:
46
>                 process.functions.append(self.parse_function())
47
>         process.main = self.main
48
>         return process
49
 
50
>     def parse_function(self):
51
>         function = Function()
52
>         function.allocator = self.allocator
53
>         stored_scope = self.scope
54
>         type_ = self.tokens.get()
55
>         name = self.tokens.get()
56
 
57
          #check if it is a global declaration
58
>         if self.tokens.peek() != "(":
59
>             if type_ not in ["int", "short", "long", "char"] + self.structs:
60
!                 self.tokens.error("unknown type")
61
>             return self.parse_global_declaration(type_, name)
62
 
63
          #otherwise continue parsing a function
64
>         self.tokens.expect("(")
65
>         function.name = name
66
>         function.type_ = type_
67
>         function.return_address = self.allocator.new(function.name+" return address")
68
>         if type_ not in ["int", "short", "long", "char", "void"]:
69
!             self.tokens.error("unknown type")
70
>         if type_ != "void":
71
>             function.return_value = self.allocator.new(function.name+" return value")
72
>         function.arguments = []
73
>         while self.tokens.peek() != ")":
74
>             type_ = self.tokens.get()
75
>             if type_ not in ["int", "short", "long", "char"]:
76
!                 self.tokens.error("unknown type")
77
>             argument = self.tokens.get()
78
>             if self.tokens.peek() == "[":
79
>                 self.tokens.expect("[")
80
>                 self.tokens.expect("]")
81
>                 type_+="[]"
82
>             function.arguments.append(Argument(argument, type_, self))
83
>             if self.tokens.peek() == ",":
84
>                 self.tokens.expect(",")
85
>             else:
86
>                 break
87
>         self.tokens.expect(")")
88
>         self.function = function
89
>         function.statement = self.parse_statement()
90
>         if type_ != "void" and not hasattr(function, "return_statement"):
91
>             self.tokens.error("Function must have a return statement")
92
>         self.function = None
93
>         self.scope = stored_scope
94
>         self.scope[function.name] = function
95
          #main thread is last function
96
>         self.main = function
97
>         return function
98
 
99
>     def parse_break(self):
100
>         break_ = Break()
101
>         break_.loop = self.loop
102
>         self.tokens.expect("break")
103
>         self.tokens.expect(";")
104
>         return break_
105
 
106
>     def parse_continue(self):
107
>         continue_ = Continue()
108
>         continue_.loop = self.loop
109
>         self.tokens.expect("continue")
110
>         self.tokens.expect(";")
111
>         return continue_
112
 
113
>     def parse_return(self):
114
>         return_ = Return()
115
>         return_.function = self.function
116
>         self.function.return_statement = return_
117
>         self.tokens.expect("return")
118
>         if hasattr(self.function, "return_value"):
119
>             return_.expression = self.parse_expression()
120
>         self.tokens.expect(";")
121
>         return return_
122
 
123
>     def parse_assert(self):
124
>         assert_ = Assert()
125
>         assert_.allocator = self.allocator
126
>         self.tokens.expect("assert")
127
>         self.tokens.expect("(")
128
>         assert_.expression = self.parse_expression()
129
>         self.tokens.expect(")")
130
>         self.tokens.expect(";")
131
>         assert_.line = self.tokens.lineno
132
>         assert_.filename = self.tokens.filename
133
>         return assert_
134
 
135
>     def parse_report(self):
136
>         report_ = Report()
137
>         report_.allocator = self.allocator
138
>         self.tokens.expect("report")
139
>         self.tokens.expect("(")
140
>         report_.expression = self.parse_expression()
141
>         self.tokens.expect(")")
142
>         self.tokens.expect(";")
143
>         report_.line = self.tokens.lineno
144
>         report_.filename = self.tokens.filename
145
>         return report_
146
 
147
>     def parse_wait_clocks(self):
148
>         wait_clocks = WaitClocks()
149
>         wait_clocks.allocator = self.allocator
150
>         self.tokens.expect("wait_clocks")
151
>         self.tokens.expect("(")
152
>         wait_clocks.expression = self.parse_expression()
153
>         self.tokens.expect(")")
154
>         self.tokens.expect(";")
155
>         wait_clocks.line = self.tokens.lineno
156
>         return wait_clocks
157
 
158
>     def parse_statement(self):
159
>         if self.tokens.peek() in ["int", "short", "long", "char"] + self.structs:
160
>             return self.parse_compound_declaration()
161
>         elif self.tokens.peek() == "struct":
162
>             return self.parse_struct_declaration()
163
>         elif self.tokens.peek() == "if":
164
>             return self.parse_if()
165
>         elif self.tokens.peek() == "while":
166
>             return self.parse_while()
167
>         elif self.tokens.peek() == "for":
168
>             return self.parse_for()
169
>         elif self.tokens.peek() == "return":
170
>             return self.parse_return()
171
>         elif self.tokens.peek() == "break":
172
>             return self.parse_break()
173
>         elif self.tokens.peek() == "continue":
174
>             return self.parse_continue()
175
>         elif self.tokens.peek() == "{":
176
>             return self.parse_block()
177
>         elif self.tokens.peek() == "assert":
178
>             return self.parse_assert()
179
>         elif self.tokens.peek() == "report":
180
>             return self.parse_report()
181
>         elif self.tokens.peek() == "switch":
182
>             return self.parse_switch()
183
>         elif self.tokens.peek() == "case":
184
>             return self.parse_case()
185
>         elif self.tokens.peek() == "default":
186
>             return self.parse_default()
187
>         elif self.tokens.peek() == "wait_clocks":
188
>             return self.parse_wait_clocks()
189
>         else:
190
>             expression = self.parse_discard()
191
>             self.tokens.expect(";")
192
>             return expression
193
 
194
>     def parse_discard(self):
195
>         return DiscardExpression(self.parse_expression(), self.allocator)
196
 
197
>     def parse_assignment(self):
198
>         assignment_operators = [
199
>             "=", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "<<=", ">>=",
200
>             "++", "--"
201
>         ]
202
>         lvalue = self.parse_ternary_expression()
203
>         if self.tokens.peek() in assignment_operators:
204
>             if not hasattr(lvalue, "declaration"):
205
>                 self.tokens.error(
206
>                     "left hand operand of assignment is not modifiable"
207
>                 )
208
>             operator = self.tokens.get()
209
>             if operator == "=":
210
>                 expression = self.parse_ternary_expression()
211
>             elif operator in ["++", "--"]:
212
>                 expression = Binary(
213
>                     operator[:-1],
214
>                     lvalue,
215
>                     Constant(1),
216
>                     self.allocator
217
>                 )
218
>             else:
219
>                 expression = Binary(
220
>                     operator[:-1],
221
>                     lvalue,
222
>                     self.parse_ternary_expression(),
223
>                     self.allocator
224
>                 )
225
>             if lvalue.type_ != expression.type_:
226
>                 self.tokens.error(
227
>                     "type mismatch in assignment"
228
>                 )
229
>             return Assignment(lvalue, expression, self.allocator)
230
>         else:
231
>             return lvalue
232
 
233
 
234
>     def parse_if(self):
235
>         if_ = If()
236
>         if_.allocator = self.allocator
237
>         self.tokens.expect("if")
238
>         self.tokens.expect("(")
239
>         if_.expression = self.parse_expression()
240
>         if if_.expression.type_ not in ["int", "short", "long", "char"]:
241
>             self.tokens.error(
242
>                 "if statement conditional must be an integer like expression"
243
>             )
244
>         self.tokens.expect(")")
245
>         if_.true_statement = self.parse_statement()
246
>         if self.tokens.peek() == "else":
247
>             self.tokens.expect("else")
248
>             if_.false_statement = self.parse_statement()
249
>         else:
250
>             if_.false_statement = None
251
>         return optimise_if(if_)
252
 
253
>     def parse_switch(self):
254
>         switch = Switch()
255
>         switch.cases = {}
256
>         self.tokens.expect("switch")
257
>         self.tokens.expect("(")
258
>         expression = self.parse_expression()
259
>         if expression.type_ not in ["int", "short", "long", "char"]:
260
>             self.tokens.error(
261
>                 "switch statement expression must be an integer like expression"
262
>             )
263
>         self.tokens.expect(")")
264
>         stored_loop = self.loop
265
>         self.loop = switch
266
>         statement = self.parse_statement()
267
>         self.loop = stored_loop
268
>         switch.expression = expression
269
>         switch.allocator = self.allocator
270
>         switch.statement = statement
271
>         return switch
272
 
273
>     def parse_case(self):
274
>         self.tokens.expect("case")
275
>         expression = self.parse_expression()
276
>         if expression.type_ not in ["int", "short", "long", "char"]:
277
>             self.tokens.error(
278
>                 "case expression must be an integer like expression"
279
>             )
280
>         self.tokens.expect(":")
281
>         try:
282
>             expression = value(expression)
283
>             case = Case()
284
>             self.loop.cases[expression] =    case
285
>         except NotConstant:
286
>             self.tokens.error("case expression must be constant")
287
>         except AttributeError:
288
>             self.tokens.error(
289
>                 "case statements may only be use inside a switch statment"
290
>             )
291
>         return case
292
 
293
>     def parse_default(self):
294
>         self.tokens.expect("default")
295
>         self.tokens.expect(":")
296
>         default = Default()
297
>         if not hasattr(self.loop, "cases"):
298
>             self.tokens.error(
299
>                 "default statements may only be used inside a switch statment"
300
>             )
301
>         if hasattr(self.loop, "default"):
302
>             self.tokens.error(
303
>                 "A switch statement may only have one default statement"
304
>             )
305
>         self.loop.default=default
306
>         return default
307
 
308
>     def parse_while(self):
309
>         loop = Loop()
310
>         self.tokens.expect("while")
311
>         self.tokens.expect("(")
312
>         expression = self.parse_expression()
313
>         self.tokens.expect(")")
314
>         stored_loop = self.loop
315
>         self.loop = loop
316
>         statement = self.parse_statement()
317
>         self.loop = stored_loop
318
 
319
>         if_ = If()
320
>         break_ = Break()
321
>         break_.loop = loop
322
>         if_.allocator = self.allocator
323
>         if expression.type_ not in ["int", "short", "long", "char"]:
324
>             self.tokens.error(
325
>                 "if statement conditional must be an integer like expression"
326
>             )
327
>         if_.expression = expression
328
>         if_.false_statement = break_
329
>         if_.true_statement = statement
330
 
331
>         loop.statement = optimise_if(if_)
332
>         return loop
333
 
334
>     def parse_for(self):
335
>         for_ = For()
336
>         for_.allocator = self.allocator
337
>         self.tokens.expect("for")
338
>         self.tokens.expect("(")
339
>         if self.tokens.peek() != ";":
340
>             for_.statement1 = self.parse_discard()
341
>         self.tokens.expect(";")
342
>         if self.tokens.peek() != ";":
343
>             for_.expression = self.parse_expression()
344
>             if for_.expression.type_ not in ["int", "short", "long", "char"]:
345
>                 self.tokens.error(
346
>                     "for statement conditional must be an integer like expression"
347
>                 )
348
>         self.tokens.expect(";")
349
>         if self.tokens.peek() != ")":
350
>             for_.statement2 = self.parse_discard()
351
>         self.tokens.expect(")")
352
>         stored_loop = self.loop
353
>         self.loop = for_
354
>         for_.statement3 = self.parse_statement()
355
>         self.loop = stored_loop
356
>         return for_
357
 
358
>     def parse_block(self):
359
>         block = Block()
360
>         stored_scope = self.scope
361
>         self.tokens.expect("{")
362
>         block.statements = []
363
>         while self.tokens.peek() != "}":
364
>             block.statements.append(self.parse_statement())
365
>         self.tokens.expect("}")
366
>         self.scope = stored_scope
367
>         return block
368
 
369
>     def parse_struct_body(self):
370
>         self.tokens.expect("{")
371
>         members = {}
372
>         while self.tokens.peek() != "}":
373
>             type_ = self.tokens.get()
374
>             name = self.tokens.get()
375
>             members[name] = self.parse_declaration(type_, name)
376
>             self.tokens.expect(";")
377
>         self.tokens.expect("}")
378
>         return members
379
 
380
>     def parse_typedef_struct(self):
381
>         self.tokens.expect("typedef")
382
>         self.tokens.expect("struct")
383
>         declaration = StructDeclaration(self.parse_struct_body())
384
>         name = self.tokens.get()
385
>         self.tokens.expect(";")
386
>         self.scope[name] = declaration
387
>         self.structs.append(name)
388
 
389
>     def parse_define_struct(self):
390
>         self.tokens.expect("struct")
391
>         name = self.tokens.get()
392
>         declaration = StructDeclaration(self.parse_struct_body())
393
>         self.tokens.expect(";")
394
>         self.scope[name] = declaration
395
 
396
>     def parse_struct_declaration(self):
397
>         self.tokens.expect("struct")
398
>         struct_name = self.tokens.get()
399
>         name = self.tokens.get()
400
>         self.tokens.expect(";")
401
>         instance = self.scope[struct_name].instance()
402
>         self.scope[name] = instance
403
>         return instance
404
 
405
>     def parse_global_declaration(self, type_, name):
406
>         instances = []
407
>         while True:
408
>             instance = self.parse_declaration(type_, name).instance()
409
>             self.scope[name] = instance
410
>             instances.append(instance)
411
>             if self.tokens.peek() == ",":
412
>                 self.tokens.expect(",")
413
>             else:
414
>                 break
415
>             name = self.tokens.get()
416
>         self.tokens.expect(";")
417
>         return CompoundDeclaration(instances)
418
 
419
>     def parse_compound_declaration(self):
420
>         type_ = self.tokens.get()
421
>         instances = []
422
>         while True:
423
>             name = self.tokens.get()
424
>             instance = self.parse_declaration(type_, name).instance()
425
>             self.scope[name] = instance
426
>             instances.append(instance)
427
>             if self.tokens.peek() == ",":
428
>                 self.tokens.expect(",")
429
>             else:
430
>                 break
431
>             name = None
432
>         self.tokens.expect(";")
433
>         return CompoundDeclaration(instances)
434
 
435
>     def parse_declaration(self, type_, name):
436
          #struct declaration
437
>         if type_ in self.structs:
438
>             declaration = self.scope[type_]
439
>         elif type_ in ["int", "short", "long", "char"]:
440
              #array declaration
441
>             if self.tokens.peek() == "[":
442
>                 size = None
443
>                 self.tokens.expect("[")
444
>                 if self.tokens.peek() != "]":
445
>                     size = self.tokens.get()
446
>                 self.tokens.expect("]")
447
>                 initializer = None
448
>                 if self.tokens.peek() == "=":
449
>                     self.tokens.expect("=")
450
>                     initializer = self.tokens.get()
451
>                     initializer = [ord(i) for i in initializer.strip('"')] + [0]
452
>                     size = len(initializer)
453
>                 if size is None:
454
>                     self.tokens.error("array size must be specified if not initialized")
455
>                 type_+="[]"
456
>                 declaration = ArrayDeclaration(self.allocator, size, type_, initializer)
457
 
458
              #simple variable declaration
459
>             else:
460
>                 if self.tokens.peek() == "=":
461
>                     self.tokens.expect("=")
462
>                     initializer = self.parse_ternary_expression()
463
>                 else:
464
>                     initializer = Constant(0)
465
>                 declaration = VariableDeclaration(
466
>                     self.allocator,
467
>                     initializer,
468
>                     name,
469
>                     type_
470
>                 )
471
 
472
>         return declaration
473
 
474
>     def parse_expression(self):
475
>         expression = self.parse_assignment()
476
>         return expression
477
 
478
>     def parse_ternary_expression(self):
479
>         expression = constant_fold(self.parse_or_expression())
480
>         while self.tokens.peek() in ["?"]:
481
>             self.tokens.expect("?")
482
>             true_expression = constant_fold(self.parse_or_expression())
483
>             self.tokens.expect(":")
484
>             false_expression = constant_fold(self.parse_or_expression())
485
>             expression = OR(AND(expression, true_expression), false_expression)
486
>         return expression
487
 
488
>     def parse_or_expression(self):
489
>         expression = self.parse_and_expression()
490
>         while self.tokens.peek() in ["||"]:
491
>             self.tokens.expect("||")
492
>             expression = OR(expression, self.parse_and_expression())
493
>         return expression
494
 
495
>     def parse_and_expression(self):
496
>         expression = self.parse_binary_expression(["|"])
497
>         while self.tokens.peek() in ["&&"]:
498
>             self.tokens.expect("&&")
499
>             expression = AND(expression, self.parse_binary_expression(["|"]))
500
>         return expression
501
 
502
>     def parse_binary_expression(self, operators):
503
>         operator_precedence = {
504
>                 "|": ["^"],
505
>                 "^": ["&"],
506
>                 "&": ["==", "!="],
507
>                 "==": ["<", ">", "<=", ">="],
508
>                 "<": ["<<", ">>"],
509
>                 "<<": ["+", "-"],
510
>                 "+": ["*", "/", "%"],
511
>         }
512
>         if operators[0] not in operator_precedence:
513
>             expression = self.parse_unary_expression()
514
>             while self.tokens.peek() in operators:
515
>                 expression = Binary(
516
>                     self.tokens.get(),
517
>                     expression,
518
>                     self.parse_unary_expression(),
519
>                     self.allocator
520
>                 )
521
>             return expression
522
>         else:
523
>             next_operators = operator_precedence[operators[0]]
524
>             expression = self.parse_binary_expression(next_operators)
525
>             while self.tokens.peek() in operators:
526
>                 expression = Binary(
527
>                     self.tokens.get(),
528
>                     expression,
529
>                     self.parse_binary_expression(next_operators),
530
>                     self.allocator
531
>                 )
532
>             return expression
533
 
534
>     def parse_unary_expression(self):
535
>         if self.tokens.peek() == "!":
536
>             operator = self.tokens.get()
537
>             expression = self.parse_paren_expression()
538
>             return Binary("==", expression, Constant(0), self.allocator)
539
>         elif self.tokens.peek() == "-":
540
>             operator = self.tokens.get()
541
>             expression = self.parse_paren_expression()
542
>             return Binary("-", Constant(0), expression, self.allocator)
543
>         elif self.tokens.peek() == "~":
544
>             operator = self.tokens.get()
545
>             expression = self.parse_paren_expression()
546
>             return Unary("~", expression)
547
>         else:
548
>             return self.parse_paren_expression()
549
 
550
>     def parse_paren_expression(self):
551
>         if self.tokens.peek() == "(":
552
>             self.tokens.expect("(")
553
>             expression = self.parse_expression()
554
>             self.tokens.expect(")")
555
>         else:
556
>             expression = self.parse_number_or_variable()
557
>         return expression
558
 
559
>     def parse_number_or_variable(self):
560
>         if self.tokens.peek()[0].isalpha():
561
>             name = self.tokens.get()
562
>             if self.tokens.peek() == "(":
563
>                 return self.parse_function_call(name)
564
>             else:
565
>                 return self.parse_variable(name)
566
>         else:
567
>             return self.parse_number()
568
 
569
>     def parse_input(self, name):
570
>         input_name = name.replace("input_", "")
571
>         self.tokens.expect("(")
572
>         self.tokens.expect(")")
573
>         return Input(input_name)
574
 
575
>     def parse_ready(self, name):
576
>         input_name = name.replace("ready_", "")
577
>         self.tokens.expect("(")
578
>         self.tokens.expect(")")
579
>         return Ready(input_name)
580
 
581
>     def parse_output(self, name):
582
>         output_name = name.replace("output_", "")
583
>         self.tokens.expect("(")
584
>         expression = self.parse_expression()
585
>         self.tokens.expect(")")
586
>         return Output(output_name, expression)
587
 
588
>     def parse_function_call(self, name):
589
>         if name.startswith("input_"):
590
>             return self.parse_input(name)
591
>         if name.startswith("ready_"):
592
>             return self.parse_ready(name)
593
>         if name.startswith("output_"):
594
>             return self.parse_output(name)
595
>         function_call = FunctionCall()
596
>         function_call.arguments = []
597
>         self.tokens.expect("(")
598
>         while self.tokens.peek() != ")":
599
>             function_call.arguments.append(self.parse_expression())
600
>             if self.tokens.peek() == ",":
601
>                 self.tokens.expect(",")
602
>             else:
603
>                 break
604
>         self.tokens.expect(")")
605
 
606
>         if name not in self.scope:
607
>             self.tokens.error("Unknown function: %s"%name)
608
 
609
>         function_call.function = self.scope[name]
610
>         function_call.type_ = function_call.function.type_
611
>         required_arguments = len(function_call.function.arguments)
612
>         actual_arguments = len(function_call.arguments)
613
>         if required_arguments != actual_arguments:
614
>             self.tokens.error("Function %s takes %s arguments %s given."%(
615
>                 name,
616
>                 len(function_call.function.arguments),
617
>                 len(function_call.arguments)
618
>             ))
619
>         required_arguments = function_call.function.arguments
620
>         actual_arguments = function_call.arguments
621
>         for required, actual in zip(required_arguments, actual_arguments):
622
>             if required.type_ != actual.type_:
623
>                 self.tokens.error("Type mismatch expected type : %s got: %s."%(
624
>                     required.type_,
625
>                     actual.type_
626
>                 ))
627
 
628
 
629
>         return function_call
630
 
631
>     def parse_number(self):
632
>         token = self.tokens.get()
633
>         if token.startswith("'"):
634
>             try:
635
>                 token = eval(token)
636
>                 value = ord(token)
637
!             except SyntaxError:
638
!                 self.tokens.error("%s is not a character literal"%token)
639
>         else:
640
>             try:
641
>                 value = int(eval(token))
642
>             except SyntaxError:
643
>                 self.tokens.error("%s is not an integer literal"%token)
644
>         return Constant(value)
645
 
646
>     def parse_variable(self, name):
647
>         if name not in self.scope:
648
>             self.tokens.error("Unknown variable: %s"%name)
649
>         instance = self.scope[name]
650
>         return self.parse_variable_array_struct(instance)
651
 
652
>     def parse_variable_array_struct(self, instance):
653
>         if instance.type_ in ["int", "short", "long", "char"]:
654
>             return Variable(instance, self.allocator)
655
>         elif instance.type_.endswith("[]"):
656
>             if self.tokens.peek() == "[":
657
>                 self.tokens.expect("[")
658
>                 index_expression = self.parse_expression()
659
>                 self.tokens.expect("]")
660
>                 if index_expression.type_ not in ["int", "short", "long", "char"]:
661
>                     self.tokens.error(
662
>                         "array indices must be an integer like expression"
663
>                     )
664
>                 return ArrayIndex(instance, index_expression, self.allocator)
665
>             else:
666
>                 return Array(instance, self.allocator)
667
>         elif instance.type_ == "struct":
668
>             self.tokens.expect(".")
669
>             member = self.tokens.get()
670
>             instance = instance.members[member]
671
>             return self.parse_variable_array_struct(instance)

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.