1 /* 2 * Hunt - A high-level D Programming Language Web framework that encourages rapid development and clean, pragmatic design. 3 * 4 * Copyright (C) 2015-2019, HuntLabs 5 * 6 * Website: https://www.huntlabs.net/ 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.framework.view.ast.Node; 13 14 public 15 { 16 import std.typecons : Nullable, nullable; 17 import hunt.framework.view.Lexer : Position; 18 } 19 20 private 21 { 22 import std.meta : AliasSeq; 23 24 import hunt.framework.view.ast.Visitor; 25 } 26 27 28 alias NodeTypes = AliasSeq!( 29 TemplateNode, 30 BlockNode, 31 StmtBlockNode, 32 RawNode, 33 ExprNode, 34 UnaryOpNode, 35 BinOpNode, 36 StringNode, 37 BooleanNode, 38 NilNode, 39 ListNode, 40 DictNode, 41 NumNode, 42 IdentNode, 43 IfNode, 44 ForNode, 45 SetNode, 46 AssignableNode, 47 MacroNode, 48 CallNode, 49 InlineIfNode, 50 FilterBlockNode, 51 ImportNode, 52 IncludeNode, 53 ExtendsNode, 54 ); 55 56 57 58 interface NodeInterface 59 { 60 void accept(VisitorInterface); 61 } 62 63 64 mixin template AcceptVisitor() 65 { 66 override void accept(VisitorInterface visitor) 67 { 68 visitor.visit(this); 69 } 70 } 71 72 73 abstract class Node : NodeInterface 74 { 75 public Position pos; 76 77 void accept(VisitorInterface visitor) {} 78 } 79 80 81 class TemplateNode : Node 82 { 83 Nullable!StmtBlockNode stmt; 84 BlockNode[string] blocks; 85 86 this(Position pos, StmtBlockNode stmt, BlockNode[string] blocks) 87 { 88 this.pos = pos; 89 this.stmt = stmt.toNullable; 90 this.blocks = blocks; 91 } 92 93 mixin AcceptVisitor; 94 } 95 96 97 98 class BlockNode : Node 99 { 100 string name; 101 Nullable!Node stmt; 102 103 this(Position pos, string name, Node stmt) 104 { 105 this.pos = pos; 106 this.name = name; 107 this.stmt = stmt.toNullable; 108 } 109 110 mixin AcceptVisitor; 111 } 112 113 114 115 class StmtBlockNode : Node 116 { 117 Node[] children; 118 119 this(Position pos) 120 { 121 this.pos = pos; 122 } 123 124 mixin AcceptVisitor; 125 } 126 127 128 129 class RawNode : Node 130 { 131 string raw; 132 133 this(Position pos, string raw) 134 { 135 this.pos = pos; 136 this.raw = raw; 137 } 138 139 mixin AcceptVisitor; 140 } 141 142 143 144 class ExprNode : Node 145 { 146 Nullable!Node expr; 147 148 this(Position pos, Node expr) 149 { 150 this.pos = pos; 151 this.expr = expr.toNullable; 152 } 153 154 mixin AcceptVisitor; 155 } 156 157 158 class InlineIfNode : Node 159 { 160 Nullable!Node expr, cond, other; 161 162 this(Position pos, Node expr, Node cond, Node other) 163 { 164 this.pos = pos; 165 this.expr = expr.toNullable; 166 this.cond = cond.toNullable; 167 this.other = other.toNullable; 168 } 169 170 mixin AcceptVisitor; 171 } 172 173 174 class BinOpNode : Node 175 { 176 string op; 177 Node lhs, rhs; 178 179 this(Position pos, string op, Node lhs, Node rhs) 180 { 181 this.pos = pos; 182 this.op = op; 183 this.lhs = lhs; 184 this.rhs = rhs; 185 } 186 187 mixin AcceptVisitor; 188 } 189 190 191 class UnaryOpNode : Node 192 { 193 string op; 194 Node expr; 195 196 this(Position pos, string op, Node expr) 197 { 198 this.pos = pos; 199 this.op = op; 200 this.expr = expr; 201 } 202 203 mixin AcceptVisitor; 204 } 205 206 207 class NumNode : Node 208 { 209 enum Type 210 { 211 Integer, 212 Float, 213 } 214 215 union Data 216 { 217 long _integer; 218 double _float; 219 } 220 221 Data data; 222 Type type; 223 224 this(Position pos, long num) 225 { 226 this.pos = pos; 227 data._integer = num; 228 type = Type.Integer; 229 } 230 231 this(Position pos, double num) 232 { 233 this.pos = pos; 234 data._float = num; 235 type = Type.Float; 236 } 237 238 mixin AcceptVisitor; 239 } 240 241 242 class BooleanNode : Node 243 { 244 bool boolean; 245 246 this(Position pos, bool boolean) 247 { 248 this.pos = pos; 249 this.boolean = boolean; 250 } 251 252 mixin AcceptVisitor; 253 } 254 255 256 class NilNode : Node 257 { 258 mixin AcceptVisitor; 259 } 260 261 262 class IdentNode : Node 263 { 264 string name; 265 Node[] subIdents; 266 267 268 this(Position pos, string name, Node[] subIdents) 269 { 270 this.pos = pos; 271 this.name = name; 272 this.subIdents = subIdents; 273 } 274 275 mixin AcceptVisitor; 276 } 277 278 279 class AssignableNode : Node 280 { 281 string name; 282 Node[] subIdents; 283 284 285 this(Position pos, string name, Node[] subIdents) 286 { 287 this.pos = pos; 288 this.name = name; 289 this.subIdents = subIdents; 290 } 291 292 mixin AcceptVisitor; 293 } 294 295 296 class IfNode : Node 297 { 298 Node cond, then, other; 299 300 this(Position pos, Node cond, Node then, Node other) 301 { 302 this.pos = pos; 303 this.cond = cond; 304 this.then = then; 305 this.other = other; 306 } 307 308 mixin AcceptVisitor; 309 } 310 311 312 class ForNode : Node 313 { 314 string[] keys; 315 Nullable!Node iterable; 316 Nullable!Node block; 317 Nullable!Node other; 318 Nullable!Node cond; 319 bool isRecursive; 320 321 this(Position pos, string[] keys, Node iterable, Node block, Node other, Node cond, bool isRecursive) 322 { 323 this.pos = pos; 324 this.keys = keys; 325 this.iterable = iterable.toNullable; 326 this.block = block.toNullable; 327 this.other = other.toNullable; 328 this.cond = cond.toNullable; 329 this.isRecursive = isRecursive; 330 } 331 332 mixin AcceptVisitor; 333 } 334 335 336 class StringNode : Node 337 { 338 string str; 339 340 this(Position pos, string str) 341 { 342 this.pos = pos; 343 this.str = str; 344 } 345 346 mixin AcceptVisitor; 347 } 348 349 350 class ListNode : Node 351 { 352 Node[] list; 353 354 this(Position pos, Node[] list) 355 { 356 this.pos = pos; 357 this.list = list; 358 } 359 360 mixin AcceptVisitor; 361 } 362 363 364 class DictNode : Node 365 { 366 Node[string] dict; 367 368 this(Position pos, Node[string] dict) 369 { 370 this.pos = pos; 371 this.dict = dict; 372 } 373 374 mixin AcceptVisitor; 375 } 376 377 378 class SetNode : Node 379 { 380 Node[] assigns; 381 Node expr; 382 383 this(Position pos, Node[] assigns, Node expr) 384 { 385 this.pos = pos; 386 this.assigns = assigns; 387 this.expr = expr; 388 } 389 390 mixin AcceptVisitor; 391 } 392 393 394 class MacroNode : Node 395 { 396 string name; 397 Arg[] args; 398 Nullable!Node block; 399 bool isReturn; 400 401 this(Position pos, string name, Arg[] args, Node block, bool isReturn) 402 { 403 this.pos = pos; 404 this.name = name; 405 this.args = args; 406 this.block = block.toNullable; 407 this.isReturn = isReturn; 408 } 409 410 mixin AcceptVisitor; 411 } 412 413 414 class CallNode : Node 415 { 416 string macroName; 417 Arg[] formArgs; 418 Nullable!Node factArgs; 419 Nullable!Node block; 420 421 this(Position pos, string macroName, Arg[] formArgs, Node factArgs, Node block) 422 { 423 this.pos = pos; 424 this.macroName = macroName; 425 this.formArgs = formArgs; 426 this.factArgs = factArgs.toNullable; 427 this.block = block.toNullable; 428 } 429 430 mixin AcceptVisitor; 431 } 432 433 434 class FilterBlockNode : Node 435 { 436 string filterName; 437 Nullable!Node args; 438 Nullable!Node block; 439 440 this(Position pos, string filterName, Node args, Node block) 441 { 442 this.pos = pos; 443 this.filterName = filterName; 444 this.args = args.toNullable; 445 this.block = block.toNullable; 446 } 447 448 mixin AcceptVisitor; 449 } 450 451 452 453 class ImportNode : Node 454 { 455 struct Rename 456 { 457 string was, become; 458 } 459 460 string fileName; 461 Rename[] macrosNames; 462 Nullable!TemplateNode tmplBlock; 463 bool withContext; 464 465 this(Position pos, string fileName, Rename[] macrosNames, TemplateNode tmplBlock, bool withContext) 466 { 467 this.pos = pos; 468 this.fileName = fileName; 469 this.macrosNames = macrosNames; 470 this.tmplBlock = tmplBlock.toNullable; 471 this.withContext = withContext; 472 } 473 474 mixin AcceptVisitor; 475 } 476 477 478 479 class IncludeNode : Node 480 { 481 string fileName; 482 Nullable!TemplateNode tmplBlock; 483 bool withContext; 484 485 this(Position pos, string fileName, TemplateNode tmplBlock, bool withContext) 486 { 487 this.pos = pos; 488 this.fileName = fileName; 489 this.tmplBlock = tmplBlock.toNullable; 490 this.withContext = withContext; 491 } 492 493 mixin AcceptVisitor; 494 } 495 496 497 498 class ExtendsNode : Node 499 { 500 string fileName; 501 Nullable!TemplateNode tmplBlock; 502 503 this(Position pos, string fileName, TemplateNode tmplBlock) 504 { 505 this.pos = pos; 506 this.fileName = fileName; 507 this.tmplBlock = tmplBlock.toNullable; 508 } 509 510 mixin AcceptVisitor; 511 } 512 513 514 515 struct Arg 516 { 517 string name; 518 Nullable!Node defaultExpr; 519 520 this(string name, Node def) 521 { 522 this.name = name; 523 this.defaultExpr = def.toNullable; 524 } 525 } 526 527 528 529 auto toNullable(T)(T val) 530 if (is(T == class)) 531 { 532 if (val is null) 533 return Nullable!T.init; 534 else 535 return Nullable!T(val); 536 }