You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by jf...@apache.org on 2019/05/03 17:58:22 UTC

[plc4x] 01/01: First stage towards code-gen.

This is an automated email from the ASF dual-hosted git repository.

jfeinauer pushed a commit to branch feature/code-gen
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit df3d23ad59d72b298e3b6eee0d137c70c7afe307
Author: Julian Feinauer <j....@pragmaticminds.de>
AuthorDate: Fri May 3 19:58:10 2019 +0200

    First stage towards code-gen.
---
 sandbox/code-gen/pom.xml                           |   30 +
 .../apache/plc4x/codegen/AbstractNodeVisitor.java  |  209 ++
 .../java/org/apache/plc4x/codegen/AddNode.java     |   12 +
 .../java/org/apache/plc4x/codegen/AliasNode.java   |   34 +
 .../org/apache/plc4x/codegen/AnnAssignerNode.java  |   56 +
 .../java/org/apache/plc4x/codegen/ArgNode.java     |   34 +
 .../org/apache/plc4x/codegen/ArgumentsNode.java    |   28 +
 .../java/org/apache/plc4x/codegen/AssignNode.java  |   37 +
 .../org/apache/plc4x/codegen/AttributeNode.java    |   45 +
 .../org/apache/plc4x/codegen/AugAssignNode.java    |   45 +
 .../java/org/apache/plc4x/codegen/BinOpNode.java   |   45 +
 .../java/org/apache/plc4x/codegen/CallNode.java    |   48 +
 .../org/apache/plc4x/codegen/ClassDefNode.java     |   55 +
 .../java/org/apache/plc4x/codegen/CodePrinter.java |   56 +
 .../java/org/apache/plc4x/codegen/CompareNode.java |   48 +
 .../java/org/apache/plc4x/codegen/ContextNode.java |    4 +
 .../main/java/org/apache/plc4x/codegen/EqNode.java |   10 +
 .../java/org/apache/plc4x/codegen/ExprNode.java    |   23 +
 .../org/apache/plc4x/codegen/FunctionDefNode.java  |   61 +
 .../main/java/org/apache/plc4x/codegen/IfNode.java |   48 +
 .../org/apache/plc4x/codegen/ImportFromNode.java   |   48 +
 .../java/org/apache/plc4x/codegen/KeywordNode.java |   34 +
 .../org/apache/plc4x/codegen/LineEntryNode.java    |   28 +
 .../java/org/apache/plc4x/codegen/ListNode.java    |   37 +
 .../java/org/apache/plc4x/codegen/LoadNode.java    |   10 +
 .../java/org/apache/plc4x/codegen/ModuleNode.java  |   26 +
 .../java/org/apache/plc4x/codegen/MultNode.java    |   10 +
 .../org/apache/plc4x/codegen/NameConstantNode.java |   23 +
 .../java/org/apache/plc4x/codegen/NameNode.java    |   34 +
 .../main/java/org/apache/plc4x/codegen/Node.java   |   11 +
 .../java/org/apache/plc4x/codegen/NodeVisitor.java |   68 +
 .../java/org/apache/plc4x/codegen/NotEqNode.java   |   10 +
 .../java/org/apache/plc4x/codegen/NumNode.java     |   23 +
 .../java/org/apache/plc4x/codegen/PassNode.java    |   10 +
 .../java/org/apache/plc4x/codegen/ReturnNode.java  |   23 +
 .../java/org/apache/plc4x/codegen/StoreNode.java   |   10 +
 .../java/org/apache/plc4x/codegen/StrNode.java     |   23 +
 .../java/org/apache/plc4x/codegen/TupleNode.java   |   37 +
 .../java/org/apache/plc4x/codegen/WhileNode.java   |   48 +
 sandbox/code-gen/src/main/resources/example.json   |  142 ++
 sandbox/code-gen/src/main/resources/example2.json  | 2129 ++++++++++++++++++++
 .../org/apache/plc4x/codegen/ModuleNodeTest.java   |  170 ++
 sandbox/pom.xml                                    |    1 +
 43 files changed, 3883 insertions(+)

diff --git a/sandbox/code-gen/pom.xml b/sandbox/code-gen/pom.xml
new file mode 100644
index 0000000..4aa7a12
--- /dev/null
+++ b/sandbox/code-gen/pom.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <artifactId>plc4x-sandbox</artifactId>
+    <groupId>org.apache.plc4x.sandbox</groupId>
+    <version>0.4.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>code-gen</artifactId>
+  <dependencies>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-annotations</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-databind</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.vintage</groupId>
+      <artifactId>junit-vintage-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+
+</project>
\ No newline at end of file
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/AbstractNodeVisitor.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/AbstractNodeVisitor.java
new file mode 100644
index 0000000..d6b9e62
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/AbstractNodeVisitor.java
@@ -0,0 +1,209 @@
+package org.apache.plc4x.codegen;
+
+
+public class AbstractNodeVisitor<T> implements NodeVisitor<T> {
+
+    @Override public T visit(AugAssignNode augAssignNode) {
+        augAssignNode.getOp().accept(this);
+        augAssignNode.getTarget().accept(this);
+        augAssignNode.getValue().accept(this);
+        return null;
+    }
+
+    @Override public T visit(AddNode addNode) {
+        return null;
+    }
+
+    @Override public T visit(EqNode eqNode) {
+        return null;
+    }
+
+    @Override public T visit(IfNode ifNode) {
+        for (Node node : ifNode.getBody()) {
+            node.accept(this);
+        }
+        for (Node node : ifNode.getOrelse()) {
+            node.accept(this);
+        }
+        ifNode.getTest().accept(this);
+        return null;
+    }
+
+    @Override public T visit(WhileNode whileNode) {
+        for (Node node : whileNode.getBody()) {
+            node.accept(this);
+        }
+        for (Node node : whileNode.getOrelse()) {
+            node.accept(this);
+        }
+        whileNode.getTest().accept(this);
+        return null;
+    }
+
+    @Override public T visit(NotEqNode notEqNode) {
+        return null;
+    }
+
+    @Override public T visit(NumNode numNode) {
+        return null;
+    }
+
+    @Override public T visit(PassNode passNode) {
+        return null;
+    }
+
+    @Override public T visit(ReturnNode returnNode) {
+        returnNode.getValue().accept(this);
+        return null;
+    }
+
+    @Override public T visit(StoreNode storeNode) {
+        return null;
+    }
+
+    @Override public T visit(StrNode strNode) {
+        return null;
+    }
+
+    @Override public T visit(TupleNode tupleNode) {
+        for (Node elt : tupleNode.getElts()) {
+            elt.accept(this);
+        }
+        return null;
+    }
+
+    @Override public T visit(NameNode nameNode) {
+        return null;
+    }
+
+    @Override public T visit(NameConstantNode nameConstantNode) {
+        return null;
+    }
+
+    @Override public T visit(MultNode multNode) {
+        return null;
+    }
+
+    @Override public T visit(ModuleNode moduleNode) {
+        for (Node node : moduleNode.getBody()) {
+            node.accept(this);
+        }
+        return null;
+    }
+
+    @Override public T visit(LoadNode loadNode) {
+        return null;
+    }
+
+    @Override public T visit(ListNode listNode) {
+        for (Node elt : listNode.getElts()) {
+            elt.accept(this);
+        }
+        return null;
+    }
+
+    @Override public T visit(KeywordNode keywordNode) {
+        keywordNode.getValue().accept(this);
+        return null;
+    }
+
+    @Override public T visit(ImportFromNode importFromNode) {
+        for (Node name : importFromNode.getNames()) {
+            name.accept(this);
+        }
+        return null;
+    }
+
+    @Override public T visit(FunctionDefNode functionDefNode) {
+        functionDefNode.getArgs().accept(this);
+        for (Node node : functionDefNode.getBody()) {
+            node.accept(this);
+        }
+        if (functionDefNode.getReturns() != null) {
+            functionDefNode.getReturns().accept(this);
+        }
+        return null;
+    }
+
+    @Override public T visit(ExprNode exprNode) {
+        return exprNode.getValue().accept(this);
+    }
+
+    @Override public T visit(CompareNode compareNode) {
+        for (Node comparator : compareNode.getComparators()) {
+            comparator.accept(this);
+        }
+        compareNode.getLeft().accept(this);
+        for (Node op : compareNode.getOps()) {
+            op.accept(this);
+        }
+        return null;
+    }
+
+    @Override public T visit(AliasNode aliasNode) {
+        return null;
+    }
+
+    @Override public T visit(AnnAssignerNode annAssignerNode) {
+        annAssignerNode.getAnnotation().accept(this);
+        annAssignerNode.getTarget().accept(this);
+        if (annAssignerNode.getValue() != null) {
+            return annAssignerNode.getValue().accept(this);
+        } else {
+            return null;
+        }
+    }
+
+    @Override public T visit(ArgNode argNode) {
+        if (argNode.getAnnotation() != null) {
+            return argNode.getAnnotation().accept(this);
+        } else {
+            return null;
+        }
+    }
+
+    @Override public T visit(ClassDefNode classDefNode) {
+        for (Node basis : classDefNode.getBases()) {
+            basis.accept(this);
+        }
+        for (Node node : classDefNode.getBody()) {
+            node.accept(this);
+        }
+        return null;
+    }
+
+    @Override public T visit(CallNode callNode) {
+        for (Node arg : callNode.getArgs()) {
+            arg.accept(this);
+        }
+        for (Node keyword : callNode.getKeywords()) {
+            keyword.accept(this);
+        }
+        return callNode.getFunc().accept(this);
+    }
+
+    @Override public T visit(BinOpNode binOpNode) {
+        binOpNode.getLeft().accept(this);
+        binOpNode.getOp().accept(this);
+        binOpNode.getRight().accept(this);
+        return null;
+    }
+
+    @Override public T visit(AttributeNode attributeNode) {
+        return attributeNode.getValue().accept(this);
+    }
+
+    @Override public T visit(AssignNode assignNode) {
+        for (Node target : assignNode.getTargets()) {
+            target.accept(this);
+        }
+        return assignNode.getValue().accept(this);
+    }
+
+    @Override public T visit(ArgumentsNode argumentsNode) {
+        for (Node arg : argumentsNode.getArgs()) {
+            arg.accept(this);
+        }
+        return null;
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/AddNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/AddNode.java
new file mode 100644
index 0000000..3e794c5
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/AddNode.java
@@ -0,0 +1,12 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("Add")
+public class AddNode extends Node {
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/AliasNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/AliasNode.java
new file mode 100644
index 0000000..21d7247
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/AliasNode.java
@@ -0,0 +1,34 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("alias")
+public class AliasNode extends Node {
+
+    @JsonProperty("asname")
+    private String asname;
+
+    @JsonProperty("name")
+    private String name;
+
+    public String getAsname() {
+        return asname;
+    }
+
+    public void setAsname(String asname) {
+        this.asname = asname;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/AnnAssignerNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/AnnAssignerNode.java
new file mode 100644
index 0000000..70143b5
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/AnnAssignerNode.java
@@ -0,0 +1,56 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("AnnAssign")
+public class AnnAssignerNode extends LineEntryNode {
+
+    @JsonProperty("annotation")
+    private Node annotation;
+
+    @JsonProperty("simple")
+    private int simple;
+
+    @JsonProperty("target")
+    private Node target;
+
+    @JsonProperty("value")
+    private Node value;
+
+    public Node getAnnotation() {
+        return annotation;
+    }
+
+    public void setAnnotation(Node annotation) {
+        this.annotation = annotation;
+    }
+
+    public int getSimple() {
+        return simple;
+    }
+
+    public void setSimple(int simple) {
+        this.simple = simple;
+    }
+
+    public Node getTarget() {
+        return target;
+    }
+
+    public void setTarget(Node target) {
+        this.target = target;
+    }
+
+    public Node getValue() {
+        return value;
+    }
+
+    public void setValue(Node value) {
+        this.value = value;
+    }
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ArgNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ArgNode.java
new file mode 100644
index 0000000..7dc1757
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ArgNode.java
@@ -0,0 +1,34 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("arg")
+public class ArgNode extends LineEntryNode {
+
+    @JsonProperty("annotation")
+    private Node annotation;
+
+    @JsonProperty("arg")
+    private String arg;
+
+    public Node getAnnotation() {
+        return annotation;
+    }
+
+    public void setAnnotation(Node annotation) {
+        this.annotation = annotation;
+    }
+
+    public String getArg() {
+        return arg;
+    }
+
+    public void setArg(String arg) {
+        this.arg = arg;
+    }
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ArgumentsNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ArgumentsNode.java
new file mode 100644
index 0000000..8f4ea38
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ArgumentsNode.java
@@ -0,0 +1,28 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@JsonTypeName("arguments")
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class ArgumentsNode extends Node {
+
+    @JsonProperty("args")
+    private List<Node> args = new ArrayList<>();
+
+    public List<Node> getArgs() {
+        return args;
+    }
+
+    public void setArgs(List<Node> args) {
+        this.args = args;
+    }
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/AssignNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/AssignNode.java
new file mode 100644
index 0000000..1211b42
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/AssignNode.java
@@ -0,0 +1,37 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@JsonTypeName("Assign")
+public class AssignNode extends LineEntryNode {
+
+    @JsonProperty("targets")
+    private List<Node> targets = new ArrayList<>();
+
+    @JsonProperty("value")
+    private Node value;
+
+    public List<Node> getTargets() {
+        return targets;
+    }
+
+    public void setTargets(List<Node> targets) {
+        this.targets = targets;
+    }
+
+    public Node getValue() {
+        return value;
+    }
+
+    public void setValue(Node value) {
+        this.value = value;
+    }
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/AttributeNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/AttributeNode.java
new file mode 100644
index 0000000..648ad7b
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/AttributeNode.java
@@ -0,0 +1,45 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("Attribute")
+public class AttributeNode extends LineEntryNode {
+
+    @JsonProperty("attr")
+    private String attr;
+
+    @JsonProperty("ctx")
+    private ContextNode ctx;
+
+    @JsonProperty("value")
+    private Node value;
+
+    public String getAttr() {
+        return attr;
+    }
+
+    public void setAttr(String attr) {
+        this.attr = attr;
+    }
+
+    public ContextNode getCtx() {
+        return ctx;
+    }
+
+    public void setCtx(ContextNode ctx) {
+        this.ctx = ctx;
+    }
+
+    public Node getValue() {
+        return value;
+    }
+
+    public void setValue(Node value) {
+        this.value = value;
+    }
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/AugAssignNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/AugAssignNode.java
new file mode 100644
index 0000000..658f14c
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/AugAssignNode.java
@@ -0,0 +1,45 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("AugAssign")
+public class AugAssignNode extends LineEntryNode {
+
+    @JsonProperty("op")
+    private Node op;
+
+    @JsonProperty("target")
+    private Node target;
+
+    @JsonProperty("value")
+    private Node value;
+
+    public Node getOp() {
+        return op;
+    }
+
+    public void setOp(Node op) {
+        this.op = op;
+    }
+
+    public Node getTarget() {
+        return target;
+    }
+
+    public void setTarget(Node target) {
+        this.target = target;
+    }
+
+    public Node getValue() {
+        return value;
+    }
+
+    public void setValue(Node value) {
+        this.value = value;
+    }
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/BinOpNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/BinOpNode.java
new file mode 100644
index 0000000..aa126a5
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/BinOpNode.java
@@ -0,0 +1,45 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("BinOp")
+public class BinOpNode extends LineEntryNode {
+
+    @JsonProperty("left")
+    private Node left;
+
+    @JsonProperty("op")
+    private Node op;
+
+    @JsonProperty("right")
+    private Node right;
+
+    public Node getLeft() {
+        return left;
+    }
+
+    public void setLeft(Node left) {
+        this.left = left;
+    }
+
+    public Node getOp() {
+        return op;
+    }
+
+    public void setOp(Node op) {
+        this.op = op;
+    }
+
+    public Node getRight() {
+        return right;
+    }
+
+    public void setRight(Node right) {
+        this.right = right;
+    }
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/CallNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/CallNode.java
new file mode 100644
index 0000000..5fd598a
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/CallNode.java
@@ -0,0 +1,48 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@JsonTypeName("Call")
+public class CallNode extends LineEntryNode {
+
+    @JsonProperty("args")
+    private List<Node> args = new ArrayList<>();
+
+    @JsonProperty("func")
+    private Node func;
+
+    @JsonProperty("keywords")
+    private List<Node> keywords = new ArrayList<>();
+
+    public List<Node> getArgs() {
+        return args;
+    }
+
+    public void setArgs(List<Node> args) {
+        this.args = args;
+    }
+
+    public Node getFunc() {
+        return func;
+    }
+
+    public void setFunc(Node func) {
+        this.func = func;
+    }
+
+    public List<Node> getKeywords() {
+        return keywords;
+    }
+
+    public void setKeywords(List<Node> keywords) {
+        this.keywords = keywords;
+    }
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ClassDefNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ClassDefNode.java
new file mode 100644
index 0000000..0445741
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ClassDefNode.java
@@ -0,0 +1,55 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@JsonTypeName("ClassDef")
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class ClassDefNode extends LineEntryNode {
+
+    @JsonProperty("bases")
+    private List<Node> bases = new ArrayList<>();
+
+    @JsonProperty("body")
+    private List<Node> body = new ArrayList<>();
+
+    @JsonProperty("name")
+    private String name;
+
+    @JsonCreator
+    public ClassDefNode() {
+    }
+
+    public List<Node> getBases() {
+        return bases;
+    }
+
+    public void setBases(List<Node> bases) {
+        this.bases = bases;
+    }
+
+    public List<Node> getBody() {
+        return body;
+    }
+
+    public void setBody(List<Node> body) {
+        this.body = body;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/CodePrinter.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/CodePrinter.java
new file mode 100644
index 0000000..7040542
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/CodePrinter.java
@@ -0,0 +1,56 @@
+package org.apache.plc4x.codegen;
+
+import java.util.stream.IntStream;
+
+/**
+ * Helper class to print code.
+ */
+public class CodePrinter {
+
+    private StringBuffer buffer = new StringBuffer();
+    private int tabSize;
+
+    private int intendationLvl = 0;
+
+    public CodePrinter(int tabSize) {
+        this.tabSize = tabSize;
+    }
+
+    public void startBlock() {
+        this.intendationLvl += tabSize;
+    }
+
+    public void endBlock() {
+        if (intendationLvl < tabSize) {
+            throw new RuntimeException("Closing a Block which is not open!");
+        }
+        this.intendationLvl -= tabSize;
+    }
+
+    public void write(String s) {
+        buffer.append(s);
+    }
+
+    public void startLine(String s) {
+        writeIntendation();
+    }
+
+    public void endLine() {
+        buffer.append("\n");
+    }
+
+    public void writeLine(String s) {
+        writeIntendation();
+        buffer.append(s);
+        buffer.append("\n");
+    }
+
+    private void writeIntendation() {
+        // Write the intendation
+        IntStream.range(0, intendationLvl).forEach(i -> buffer.append(" "));
+    }
+
+    public String getCode() {
+        return buffer.toString();
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/CompareNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/CompareNode.java
new file mode 100644
index 0000000..12378a5
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/CompareNode.java
@@ -0,0 +1,48 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@JsonTypeName("Compare")
+public class CompareNode extends LineEntryNode {
+
+    @JsonProperty("comparators")
+    private List<Node> comparators = new ArrayList<>();
+
+    @JsonProperty("left")
+    private Node left;
+
+    @JsonProperty("ops")
+    private List<Node> ops;
+
+    public List<Node> getComparators() {
+        return comparators;
+    }
+
+    public void setComparators(List<Node> comparators) {
+        this.comparators = comparators;
+    }
+
+    public Node getLeft() {
+        return left;
+    }
+
+    public void setLeft(Node left) {
+        this.left = left;
+    }
+
+    public List<Node> getOps() {
+        return ops;
+    }
+
+    public void setOps(List<Node> ops) {
+        this.ops = ops;
+    }
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ContextNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ContextNode.java
new file mode 100644
index 0000000..5239760
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ContextNode.java
@@ -0,0 +1,4 @@
+package org.apache.plc4x.codegen;
+
+public abstract class ContextNode extends Node {
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/EqNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/EqNode.java
new file mode 100644
index 0000000..04b84d7
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/EqNode.java
@@ -0,0 +1,10 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("Eq")
+public class EqNode extends Node {
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ExprNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ExprNode.java
new file mode 100644
index 0000000..1f8fa79
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ExprNode.java
@@ -0,0 +1,23 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("Expr")
+public class ExprNode extends LineEntryNode {
+
+    @JsonProperty("value")
+    private Node value;
+
+    public Node getValue() {
+        return value;
+    }
+
+    public void setValue(Node value) {
+        this.value = value;
+    }
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/FunctionDefNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/FunctionDefNode.java
new file mode 100644
index 0000000..188bf68
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/FunctionDefNode.java
@@ -0,0 +1,61 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@JsonTypeName("FunctionDef")
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class FunctionDefNode extends LineEntryNode {
+
+    @JsonProperty("args")
+    private ArgumentsNode args;
+
+    @JsonProperty("body")
+    private List<Node> body = new ArrayList<>();
+
+    @JsonProperty("name")
+    private String name;
+
+    @JsonProperty("returns")
+    private Node returns;
+
+    public ArgumentsNode getArgs() {
+        return args;
+    }
+
+    public void setArgs(ArgumentsNode args) {
+        this.args = args;
+    }
+
+    public List<Node> getBody() {
+        return body;
+    }
+
+    public void setBody(List<Node> body) {
+        this.body = body;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Node getReturns() {
+        return returns;
+    }
+
+    public void setReturns(Node returns) {
+        this.returns = returns;
+    }
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/IfNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/IfNode.java
new file mode 100644
index 0000000..5deef16
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/IfNode.java
@@ -0,0 +1,48 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@JsonTypeName("If")
+public class IfNode extends LineEntryNode {
+
+    @JsonProperty("body")
+    private List<Node> body = new ArrayList<>();
+
+    @JsonProperty("orelse")
+    private List<Node> orelse = new ArrayList<>();
+
+    @JsonProperty("test")
+    private Node test;
+
+    public List<Node> getBody() {
+        return body;
+    }
+
+    public void setBody(List<Node> body) {
+        this.body = body;
+    }
+
+    public List<Node> getOrelse() {
+        return orelse;
+    }
+
+    public void setOrelse(List<Node> orelse) {
+        this.orelse = orelse;
+    }
+
+    public Node getTest() {
+        return test;
+    }
+
+    public void setTest(Node test) {
+        this.test = test;
+    }
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ImportFromNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ImportFromNode.java
new file mode 100644
index 0000000..fc572c1
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ImportFromNode.java
@@ -0,0 +1,48 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@JsonTypeName("ImportFrom")
+public class ImportFromNode extends LineEntryNode {
+
+    @JsonProperty("level")
+    private long level;
+
+    @JsonProperty("module")
+    private String module;
+
+    @JsonProperty("names")
+    private List<Node> names = new ArrayList<>();
+
+    public long getLevel() {
+        return level;
+    }
+
+    public void setLevel(long level) {
+        this.level = level;
+    }
+
+    public String getModule() {
+        return module;
+    }
+
+    public void setModule(String module) {
+        this.module = module;
+    }
+
+    public List<Node> getNames() {
+        return names;
+    }
+
+    public void setNames(List<Node> names) {
+        this.names = names;
+    }
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/KeywordNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/KeywordNode.java
new file mode 100644
index 0000000..0dfe54a
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/KeywordNode.java
@@ -0,0 +1,34 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("keyword")
+public class KeywordNode extends Node {
+
+    @JsonProperty("arg")
+    private String arg;
+
+    @JsonProperty("value")
+    private Node value;
+
+    public String getArg() {
+        return arg;
+    }
+
+    public void setArg(String arg) {
+        this.arg = arg;
+    }
+
+    public Node getValue() {
+        return value;
+    }
+
+    public void setValue(Node value) {
+        this.value = value;
+    }
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/LineEntryNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/LineEntryNode.java
new file mode 100644
index 0000000..017ded2
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/LineEntryNode.java
@@ -0,0 +1,28 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public abstract class LineEntryNode extends Node {
+
+    @JsonProperty("col_offset")
+    private long colOffset;
+
+    @JsonProperty("lineno")
+    private long lineno;
+
+    public long getColOffset() {
+        return colOffset;
+    }
+
+    public void setColOffset(long colOffset) {
+        this.colOffset = colOffset;
+    }
+
+    public long getLineno() {
+        return lineno;
+    }
+
+    public void setLineno(long lineno) {
+        this.lineno = lineno;
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ListNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ListNode.java
new file mode 100644
index 0000000..32f6e90
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ListNode.java
@@ -0,0 +1,37 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@JsonTypeName("List")
+public class ListNode extends LineEntryNode {
+
+    @JsonProperty("ctx")
+    private ContextNode ctx;
+
+    @JsonProperty("elts")
+    private List<Node> elts = new ArrayList<>();
+
+    public ContextNode getCtx() {
+        return ctx;
+    }
+
+    public void setCtx(ContextNode ctx) {
+        this.ctx = ctx;
+    }
+
+    public List<Node> getElts() {
+        return elts;
+    }
+
+    public void setElts(List<Node> elts) {
+        this.elts = elts;
+    }
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/LoadNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/LoadNode.java
new file mode 100644
index 0000000..cdf5327
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/LoadNode.java
@@ -0,0 +1,10 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("Load")
+public class LoadNode extends ContextNode {
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ModuleNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ModuleNode.java
new file mode 100644
index 0000000..b17ea2d
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ModuleNode.java
@@ -0,0 +1,26 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@JsonTypeName("Module")
+public class ModuleNode extends Node {
+
+    @JsonProperty
+    private List<Node> body = new ArrayList<>();
+
+    public List<Node> getBody() {
+        return body;
+    }
+
+    public void setBody(List<Node> body) {
+        this.body = body;
+    }
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
\ No newline at end of file
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/MultNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/MultNode.java
new file mode 100644
index 0000000..1cecd78
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/MultNode.java
@@ -0,0 +1,10 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("Mult")
+public class MultNode extends LineEntryNode {
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/NameConstantNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/NameConstantNode.java
new file mode 100644
index 0000000..13decf1
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/NameConstantNode.java
@@ -0,0 +1,23 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("NameConstant")
+public class NameConstantNode extends LineEntryNode {
+
+    @JsonProperty("value")
+    private boolean value;
+
+    public boolean isValue() {
+        return value;
+    }
+
+    public void setValue(boolean value) {
+        this.value = value;
+    }
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/NameNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/NameNode.java
new file mode 100644
index 0000000..c2a5d2f
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/NameNode.java
@@ -0,0 +1,34 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("Name")
+public class NameNode extends LineEntryNode {
+
+    @JsonProperty("ctx")
+    private ContextNode ctx;
+
+    @JsonProperty("id")
+    private String id;
+
+    public ContextNode getCtx() {
+        return ctx;
+    }
+
+    public void setCtx(ContextNode ctx) {
+        this.ctx = ctx;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/Node.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/Node.java
new file mode 100644
index 0000000..d8918ce
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/Node.java
@@ -0,0 +1,11 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+@JsonTypeInfo(
+    use = JsonTypeInfo.Id.NAME,
+    property = "_type")
+public abstract class Node {
+
+    public abstract <T> T accept(NodeVisitor<T> visitor);
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/NodeVisitor.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/NodeVisitor.java
new file mode 100644
index 0000000..f712f05
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/NodeVisitor.java
@@ -0,0 +1,68 @@
+package org.apache.plc4x.codegen;
+
+public interface NodeVisitor<T> {
+
+    T visit(AugAssignNode augAssignNode);
+
+    T visit(AddNode addNode);
+
+    T visit(EqNode eqNode);
+
+    T visit(IfNode ifNode);
+
+    T visit(WhileNode whileNode);
+
+    T visit(NotEqNode notEqNode);
+
+    T visit(NumNode numNode);
+
+    T visit(PassNode passNode);
+
+    T visit(ReturnNode returnNode);
+
+    T visit(StoreNode storeNode);
+
+    T visit(StrNode strNode);
+
+    T visit(TupleNode tupleNode);
+
+    T visit(NameNode nameNode);
+
+    T visit(NameConstantNode nameConstantNode);
+
+    T visit(MultNode multNode);
+
+    T visit(ModuleNode moduleNode);
+
+    T visit(LoadNode loadNode);
+
+    T visit(ListNode listNode);
+
+    T visit(KeywordNode keywordNode);
+
+    T visit(ImportFromNode importFromNode);
+
+    T visit(FunctionDefNode functionDefNode);
+
+    T visit(ExprNode exprNode);
+
+    T visit(CompareNode compareNode);
+
+    T visit(AliasNode aliasNode);
+
+    T visit(AnnAssignerNode annAssignerNode);
+
+    T visit(ArgNode argNode);
+
+    T visit(ClassDefNode classDefNode);
+
+    T visit(CallNode callNode);
+
+    T visit(BinOpNode binOpNode);
+
+    T visit(AttributeNode attributeNode);
+
+    T visit(AssignNode assignNode);
+
+    T visit(ArgumentsNode argumentsNode);
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/NotEqNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/NotEqNode.java
new file mode 100644
index 0000000..60476f9
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/NotEqNode.java
@@ -0,0 +1,10 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("NotEq")
+public class NotEqNode extends Node {
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/NumNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/NumNode.java
new file mode 100644
index 0000000..57c6f9d
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/NumNode.java
@@ -0,0 +1,23 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("Num")
+public class NumNode extends LineEntryNode {
+
+    @JsonProperty("n")
+    private double n;
+
+    public double getN() {
+        return n;
+    }
+
+    public void setN(double n) {
+        this.n = n;
+    }
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/PassNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/PassNode.java
new file mode 100644
index 0000000..ca5b611
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/PassNode.java
@@ -0,0 +1,10 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("Pass")
+public class PassNode extends LineEntryNode {
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ReturnNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ReturnNode.java
new file mode 100644
index 0000000..22235fa
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/ReturnNode.java
@@ -0,0 +1,23 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("Return")
+public class ReturnNode extends LineEntryNode {
+
+    @JsonProperty("value")
+    private Node value;
+
+    public Node getValue() {
+        return value;
+    }
+
+    public void setValue(Node value) {
+        this.value = value;
+    }
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/StoreNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/StoreNode.java
new file mode 100644
index 0000000..8ac8205
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/StoreNode.java
@@ -0,0 +1,10 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("Store")
+public class StoreNode extends ContextNode {
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/StrNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/StrNode.java
new file mode 100644
index 0000000..5bf0854
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/StrNode.java
@@ -0,0 +1,23 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("Str")
+public class StrNode extends LineEntryNode {
+
+    @JsonProperty("s")
+    private String s;
+
+    public String getS() {
+        return s;
+    }
+
+    public void setS(String s) {
+        this.s = s;
+    }
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/TupleNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/TupleNode.java
new file mode 100644
index 0000000..0c06728
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/TupleNode.java
@@ -0,0 +1,37 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@JsonTypeName("Tuple")
+public class TupleNode extends LineEntryNode {
+
+    @JsonProperty("ctx")
+    private ContextNode ctx;
+
+    @JsonProperty("elts")
+    private List<Node> elts = new ArrayList<>();
+
+    public ContextNode getCtx() {
+        return ctx;
+    }
+
+    public void setCtx(ContextNode ctx) {
+        this.ctx = ctx;
+    }
+
+    public List<Node> getElts() {
+        return elts;
+    }
+
+    public void setElts(List<Node> elts) {
+        this.elts = elts;
+    }
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/WhileNode.java b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/WhileNode.java
new file mode 100644
index 0000000..19e19dc
--- /dev/null
+++ b/sandbox/code-gen/src/main/java/org/apache/plc4x/codegen/WhileNode.java
@@ -0,0 +1,48 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@JsonTypeName("While")
+public class WhileNode extends LineEntryNode {
+
+    @JsonProperty("body")
+    private List<Node> body = new ArrayList<>();
+
+    @JsonProperty("orelse")
+    private List<Node> orelse = new ArrayList<>();
+
+    @JsonProperty("test")
+    private Node test;
+
+    public List<Node> getBody() {
+        return body;
+    }
+
+    public void setBody(List<Node> body) {
+        this.body = body;
+    }
+
+    public List<Node> getOrelse() {
+        return orelse;
+    }
+
+    public void setOrelse(List<Node> orelse) {
+        this.orelse = orelse;
+    }
+
+    public Node getTest() {
+        return test;
+    }
+
+    public void setTest(Node test) {
+        this.test = test;
+    }
+
+    @Override public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}
diff --git a/sandbox/code-gen/src/main/resources/example.json b/sandbox/code-gen/src/main/resources/example.json
new file mode 100644
index 0000000..8faa3d9
--- /dev/null
+++ b/sandbox/code-gen/src/main/resources/example.json
@@ -0,0 +1,142 @@
+{
+    "_type": "Module",
+    "body": [
+        {
+            "_type": "ClassDef",
+            "bases": [],
+            "body": [
+                {
+                    "_type": "Pass",
+                    "col_offset": 4,
+                    "lineno": 5
+                }
+            ],
+            "col_offset": 0,
+            "decorator_list": [],
+            "keywords": [],
+            "lineno": 4,
+            "name": "MyClass"
+        },
+        {
+            "_type": "FunctionDef",
+            "args": {
+                "_type": "arguments",
+                "args": [],
+                "defaults": [],
+                "kw_defaults": [],
+                "kwarg": null,
+                "kwonlyargs": [],
+                "vararg": null
+            },
+            "body": [
+                {
+                    "_type": "Expr",
+                    "col_offset": 4,
+                    "lineno": 8,
+                    "value": {
+                        "_type": "Call",
+                        "args": [
+                            {
+                                "_type": "Str",
+                                "col_offset": 10,
+                                "lineno": 8,
+                                "s": "Hallo"
+                            }
+                        ],
+                        "col_offset": 4,
+                        "func": {
+                            "_type": "Name",
+                            "col_offset": 4,
+                            "ctx": {
+                                "_type": "Load"
+                            },
+                            "id": "print",
+                            "lineno": 8
+                        },
+                        "keywords": [],
+                        "lineno": 8
+                    }
+                }
+            ],
+            "col_offset": 0,
+            "decorator_list": [],
+            "lineno": 7,
+            "name": "myMethod",
+            "returns": null
+        },
+        {
+            "_type": "Expr",
+            "col_offset": 0,
+            "lineno": 10,
+            "value": {
+                "_type": "Call",
+                "args": [],
+                "col_offset": 0,
+                "func": {
+                    "_type": "Name",
+                    "col_offset": 0,
+                    "ctx": {
+                        "_type": "Load"
+                    },
+                    "id": "myMethod",
+                    "lineno": 10
+                },
+                "keywords": [],
+                "lineno": 10
+            }
+        },
+        {
+            "_type": "AnnAssign",
+            "annotation": {
+                "_type": "Name",
+                "col_offset": 3,
+                "ctx": {
+                    "_type": "Load"
+                },
+                "id": "Integer",
+                "lineno": 12
+            },
+            "col_offset": 0,
+            "lineno": 12,
+            "simple": 1,
+            "target": {
+                "_type": "Name",
+                "col_offset": 0,
+                "ctx": {
+                    "_type": "Store"
+                },
+                "id": "a",
+                "lineno": 12
+            },
+            "value": {
+                "_type": "Num",
+                "col_offset": 13,
+                "lineno": 12,
+                "n": 5
+            }
+        },
+        {
+            "_type": "AugAssign",
+            "col_offset": 0,
+            "lineno": 14,
+            "op": {
+                "_type": "Add"
+            },
+            "target": {
+                "_type": "Name",
+                "col_offset": 0,
+                "ctx": {
+                    "_type": "Store"
+                },
+                "id": "a",
+                "lineno": 14
+            },
+            "value": {
+                "_type": "Num",
+                "col_offset": 5,
+                "lineno": 14,
+                "n": 1
+            }
+        }
+    ]
+}
\ No newline at end of file
diff --git a/sandbox/code-gen/src/main/resources/example2.json b/sandbox/code-gen/src/main/resources/example2.json
new file mode 100644
index 0000000..ea0f370
--- /dev/null
+++ b/sandbox/code-gen/src/main/resources/example2.json
@@ -0,0 +1,2129 @@
+{
+    "_type": "Module",
+    "body": [
+        {
+            "_type": "ImportFrom",
+            "col_offset": 0,
+            "level": 0,
+            "lineno": 1,
+            "module": "pymodbus.datastore",
+            "names": [
+                {
+                    "_type": "alias",
+                    "asname": null,
+                    "name": "ModbusSlaveContext"
+                },
+                {
+                    "_type": "alias",
+                    "asname": null,
+                    "name": "ModbusSequentialDataBlock"
+                },
+                {
+                    "_type": "alias",
+                    "asname": null,
+                    "name": "ModbusServerContext"
+                }
+            ]
+        },
+        {
+            "_type": "ImportFrom",
+            "col_offset": 0,
+            "level": 0,
+            "lineno": 2,
+            "module": "pymodbus.device",
+            "names": [
+                {
+                    "_type": "alias",
+                    "asname": null,
+                    "name": "ModbusDeviceIdentification"
+                }
+            ]
+        },
+        {
+            "_type": "ImportFrom",
+            "col_offset": 0,
+            "level": 0,
+            "lineno": 3,
+            "module": "pymodbus.server.sync",
+            "names": [
+                {
+                    "_type": "alias",
+                    "asname": null,
+                    "name": "ModbusTcpServer"
+                },
+                {
+                    "_type": "alias",
+                    "asname": null,
+                    "name": "StartTcpServer"
+                }
+            ]
+        },
+        {
+            "_type": "ImportFrom",
+            "col_offset": 0,
+            "level": 0,
+            "lineno": 5,
+            "module": "Api",
+            "names": [
+                {
+                    "_type": "alias",
+                    "asname": null,
+                    "name": "Message"
+                },
+                {
+                    "_type": "alias",
+                    "asname": null,
+                    "name": "Protocol"
+                },
+                {
+                    "_type": "alias",
+                    "asname": null,
+                    "name": "Buffer"
+                }
+            ]
+        },
+        {
+            "_type": "ClassDef",
+            "bases": [
+                {
+                    "_type": "Name",
+                    "col_offset": 17,
+                    "ctx": {
+                        "_type": "Load"
+                    },
+                    "id": "object",
+                    "lineno": 8
+                }
+            ],
+            "body": [
+                {
+                    "_type": "FunctionDef",
+                    "args": {
+                        "_type": "arguments",
+                        "args": [
+                            {
+                                "_type": "arg",
+                                "annotation": null,
+                                "arg": "self",
+                                "col_offset": 17,
+                                "lineno": 10
+                            },
+                            {
+                                "_type": "arg",
+                                "annotation": {
+                                    "_type": "Name",
+                                    "col_offset": 33,
+                                    "ctx": {
+                                        "_type": "Load"
+                                    },
+                                    "id": "Protocol",
+                                    "lineno": 10
+                                },
+                                "arg": "protocol",
+                                "col_offset": 23,
+                                "lineno": 10
+                            }
+                        ],
+                        "defaults": [],
+                        "kw_defaults": [],
+                        "kwarg": null,
+                        "kwonlyargs": [],
+                        "vararg": null
+                    },
+                    "body": [
+                        {
+                            "_type": "Assign",
+                            "col_offset": 8,
+                            "lineno": 11,
+                            "targets": [
+                                {
+                                    "_type": "Attribute",
+                                    "attr": "protocol",
+                                    "col_offset": 8,
+                                    "ctx": {
+                                        "_type": "Store"
+                                    },
+                                    "lineno": 11,
+                                    "value": {
+                                        "_type": "Name",
+                                        "col_offset": 8,
+                                        "ctx": {
+                                            "_type": "Load"
+                                        },
+                                        "id": "self",
+                                        "lineno": 11
+                                    }
+                                }
+                            ],
+                            "value": {
+                                "_type": "Name",
+                                "col_offset": 24,
+                                "ctx": {
+                                    "_type": "Load"
+                                },
+                                "id": "protocol",
+                                "lineno": 11
+                            }
+                        }
+                    ],
+                    "col_offset": 4,
+                    "decorator_list": [],
+                    "lineno": 10,
+                    "name": "__init__",
+                    "returns": null
+                },
+                {
+                    "_type": "FunctionDef",
+                    "args": {
+                        "_type": "arguments",
+                        "args": [
+                            {
+                                "_type": "arg",
+                                "annotation": null,
+                                "arg": "self",
+                                "col_offset": 16,
+                                "lineno": 13
+                            }
+                        ],
+                        "defaults": [],
+                        "kw_defaults": [],
+                        "kwarg": null,
+                        "kwonlyargs": [],
+                        "vararg": null
+                    },
+                    "body": [
+                        {
+                            "_type": "Pass",
+                            "col_offset": 8,
+                            "lineno": 14
+                        }
+                    ],
+                    "col_offset": 4,
+                    "decorator_list": [],
+                    "lineno": 13,
+                    "name": "connect",
+                    "returns": null
+                }
+            ],
+            "col_offset": 0,
+            "decorator_list": [],
+            "keywords": [],
+            "lineno": 8,
+            "name": "DriverBase"
+        },
+        {
+            "_type": "ClassDef",
+            "bases": [
+                {
+                    "_type": "Name",
+                    "col_offset": 14,
+                    "ctx": {
+                        "_type": "Load"
+                    },
+                    "id": "Message",
+                    "lineno": 17
+                }
+            ],
+            "body": [
+                {
+                    "_type": "FunctionDef",
+                    "args": {
+                        "_type": "arguments",
+                        "args": [
+                            {
+                                "_type": "arg",
+                                "annotation": null,
+                                "arg": "self",
+                                "col_offset": 15,
+                                "lineno": 19
+                            },
+                            {
+                                "_type": "arg",
+                                "annotation": {
+                                    "_type": "Name",
+                                    "col_offset": 29,
+                                    "ctx": {
+                                        "_type": "Load"
+                                    },
+                                    "id": "Buffer",
+                                    "lineno": 19
+                                },
+                                "arg": "buffer",
+                                "col_offset": 21,
+                                "lineno": 19
+                            }
+                        ],
+                        "defaults": [],
+                        "kw_defaults": [],
+                        "kwarg": null,
+                        "kwonlyargs": [],
+                        "vararg": null
+                    },
+                    "body": [
+                        {
+                            "_type": "Expr",
+                            "col_offset": 8,
+                            "lineno": 20,
+                            "value": {
+                                "_type": "Call",
+                                "args": [
+                                    {
+                                        "_type": "Call",
+                                        "args": [
+                                            {
+                                                "_type": "Str",
+                                                "col_offset": 30,
+                                                "lineno": 20,
+                                                "s": "Hallo I'm a  Request"
+                                            },
+                                            {
+                                                "_type": "Str",
+                                                "col_offset": 54,
+                                                "lineno": 20,
+                                                "s": "utf-8"
+                                            }
+                                        ],
+                                        "col_offset": 20,
+                                        "func": {
+                                            "_type": "Name",
+                                            "col_offset": 20,
+                                            "ctx": {
+                                                "_type": "Load"
+                                            },
+                                            "id": "bytearray",
+                                            "lineno": 20
+                                        },
+                                        "keywords": [],
+                                        "lineno": 20
+                                    }
+                                ],
+                                "col_offset": 8,
+                                "func": {
+                                    "_type": "Attribute",
+                                    "attr": "send",
+                                    "col_offset": 8,
+                                    "ctx": {
+                                        "_type": "Load"
+                                    },
+                                    "lineno": 20,
+                                    "value": {
+                                        "_type": "Name",
+                                        "col_offset": 8,
+                                        "ctx": {
+                                            "_type": "Load"
+                                        },
+                                        "id": "buffer",
+                                        "lineno": 20
+                                    }
+                                },
+                                "keywords": [],
+                                "lineno": 20
+                            }
+                        }
+                    ],
+                    "col_offset": 4,
+                    "decorator_list": [],
+                    "lineno": 19,
+                    "name": "encode",
+                    "returns": null
+                }
+            ],
+            "col_offset": 0,
+            "decorator_list": [],
+            "keywords": [],
+            "lineno": 17,
+            "name": "Request"
+        },
+        {
+            "_type": "ClassDef",
+            "bases": [
+                {
+                    "_type": "Name",
+                    "col_offset": 15,
+                    "ctx": {
+                        "_type": "Load"
+                    },
+                    "id": "Message",
+                    "lineno": 23
+                }
+            ],
+            "body": [
+                {
+                    "_type": "FunctionDef",
+                    "args": {
+                        "_type": "arguments",
+                        "args": [
+                            {
+                                "_type": "arg",
+                                "annotation": null,
+                                "arg": "self",
+                                "col_offset": 15,
+                                "lineno": 26
+                            },
+                            {
+                                "_type": "arg",
+                                "annotation": {
+                                    "_type": "Name",
+                                    "col_offset": 29,
+                                    "ctx": {
+                                        "_type": "Load"
+                                    },
+                                    "id": "Buffer",
+                                    "lineno": 26
+                                },
+                                "arg": "buffer",
+                                "col_offset": 21,
+                                "lineno": 26
+                            }
+                        ],
+                        "defaults": [],
+                        "kw_defaults": [],
+                        "kwarg": null,
+                        "kwonlyargs": [],
+                        "vararg": null
+                    },
+                    "body": [
+                        {
+                            "_type": "Assign",
+                            "col_offset": 8,
+                            "lineno": 27,
+                            "targets": [
+                                {
+                                    "_type": "Name",
+                                    "col_offset": 8,
+                                    "ctx": {
+                                        "_type": "Store"
+                                    },
+                                    "id": "bytes",
+                                    "lineno": 27
+                                }
+                            ],
+                            "value": {
+                                "_type": "Call",
+                                "args": [],
+                                "col_offset": 16,
+                                "func": {
+                                    "_type": "Name",
+                                    "col_offset": 16,
+                                    "ctx": {
+                                        "_type": "Load"
+                                    },
+                                    "id": "bytearray",
+                                    "lineno": 27
+                                },
+                                "keywords": [],
+                                "lineno": 27
+                            }
+                        },
+                        {
+                            "_type": "Assign",
+                            "col_offset": 8,
+                            "lineno": 28,
+                            "targets": [
+                                {
+                                    "_type": "Name",
+                                    "col_offset": 8,
+                                    "ctx": {
+                                        "_type": "Store"
+                                    },
+                                    "id": "b",
+                                    "lineno": 28
+                                }
+                            ],
+                            "value": {
+                                "_type": "Call",
+                                "args": [],
+                                "col_offset": 12,
+                                "func": {
+                                    "_type": "Attribute",
+                                    "attr": "readByte",
+                                    "col_offset": 12,
+                                    "ctx": {
+                                        "_type": "Load"
+                                    },
+                                    "lineno": 28,
+                                    "value": {
+                                        "_type": "Name",
+                                        "col_offset": 12,
+                                        "ctx": {
+                                            "_type": "Load"
+                                        },
+                                        "id": "buffer",
+                                        "lineno": 28
+                                    }
+                                },
+                                "keywords": [],
+                                "lineno": 28
+                            }
+                        },
+                        {
+                            "_type": "While",
+                            "body": [
+                                {
+                                    "_type": "Expr",
+                                    "col_offset": 12,
+                                    "lineno": 30,
+                                    "value": {
+                                        "_type": "Call",
+                                        "args": [
+                                            {
+                                                "_type": "Name",
+                                                "col_offset": 25,
+                                                "ctx": {
+                                                    "_type": "Load"
+                                                },
+                                                "id": "b",
+                                                "lineno": 30
+                                            }
+                                        ],
+                                        "col_offset": 12,
+                                        "func": {
+                                            "_type": "Attribute",
+                                            "attr": "append",
+                                            "col_offset": 12,
+                                            "ctx": {
+                                                "_type": "Load"
+                                            },
+                                            "lineno": 30,
+                                            "value": {
+                                                "_type": "Name",
+                                                "col_offset": 12,
+                                                "ctx": {
+                                                    "_type": "Load"
+                                                },
+                                                "id": "bytes",
+                                                "lineno": 30
+                                            }
+                                        },
+                                        "keywords": [],
+                                        "lineno": 30
+                                    }
+                                },
+                                {
+                                    "_type": "Assign",
+                                    "col_offset": 12,
+                                    "lineno": 31,
+                                    "targets": [
+                                        {
+                                            "_type": "Name",
+                                            "col_offset": 12,
+                                            "ctx": {
+                                                "_type": "Store"
+                                            },
+                                            "id": "b",
+                                            "lineno": 31
+                                        }
+                                    ],
+                                    "value": {
+                                        "_type": "Call",
+                                        "args": [],
+                                        "col_offset": 16,
+                                        "func": {
+                                            "_type": "Attribute",
+                                            "attr": "readByte",
+                                            "col_offset": 16,
+                                            "ctx": {
+                                                "_type": "Load"
+                                            },
+                                            "lineno": 31,
+                                            "value": {
+                                                "_type": "Name",
+                                                "col_offset": 16,
+                                                "ctx": {
+                                                    "_type": "Load"
+                                                },
+                                                "id": "buffer",
+                                                "lineno": 31
+                                            }
+                                        },
+                                        "keywords": [],
+                                        "lineno": 31
+                                    }
+                                }
+                            ],
+                            "col_offset": 8,
+                            "lineno": 29,
+                            "orelse": [],
+                            "test": {
+                                "_type": "Compare",
+                                "col_offset": 14,
+                                "comparators": [
+                                    {
+                                        "_type": "Num",
+                                        "col_offset": 19,
+                                        "lineno": 29,
+                                        "n": 0
+                                    }
+                                ],
+                                "left": {
+                                    "_type": "Name",
+                                    "col_offset": 14,
+                                    "ctx": {
+                                        "_type": "Load"
+                                    },
+                                    "id": "b",
+                                    "lineno": 29
+                                },
+                                "lineno": 29,
+                                "ops": [
+                                    {
+                                        "_type": "NotEq"
+                                    }
+                                ]
+                            }
+                        },
+                        {
+                            "_type": "Expr",
+                            "col_offset": 8,
+                            "lineno": 32,
+                            "value": {
+                                "_type": "Call",
+                                "args": [
+                                    {
+                                        "_type": "Call",
+                                        "args": [
+                                            {
+                                                "_type": "Name",
+                                                "col_offset": 18,
+                                                "ctx": {
+                                                    "_type": "Load"
+                                                },
+                                                "id": "bytearray",
+                                                "lineno": 32
+                                            }
+                                        ],
+                                        "col_offset": 14,
+                                        "func": {
+                                            "_type": "Name",
+                                            "col_offset": 14,
+                                            "ctx": {
+                                                "_type": "Load"
+                                            },
+                                            "id": "str",
+                                            "lineno": 32
+                                        },
+                                        "keywords": [],
+                                        "lineno": 32
+                                    }
+                                ],
+                                "col_offset": 8,
+                                "func": {
+                                    "_type": "Name",
+                                    "col_offset": 8,
+                                    "ctx": {
+                                        "_type": "Load"
+                                    },
+                                    "id": "print",
+                                    "lineno": 32
+                                },
+                                "keywords": [],
+                                "lineno": 32
+                            }
+                        },
+                        {
+                            "_type": "Return",
+                            "col_offset": 8,
+                            "lineno": 33,
+                            "value": {
+                                "_type": "Call",
+                                "args": [],
+                                "col_offset": 15,
+                                "func": {
+                                    "_type": "Name",
+                                    "col_offset": 15,
+                                    "ctx": {
+                                        "_type": "Load"
+                                    },
+                                    "id": "Response",
+                                    "lineno": 33
+                                },
+                                "keywords": [],
+                                "lineno": 33
+                            }
+                        }
+                    ],
+                    "col_offset": 4,
+                    "decorator_list": [
+                        {
+                            "_type": "Name",
+                            "col_offset": 5,
+                            "ctx": {
+                                "_type": "Load"
+                            },
+                            "id": "classmethod",
+                            "lineno": 25
+                        }
+                    ],
+                    "lineno": 25,
+                    "name": "decode",
+                    "returns": null
+                }
+            ],
+            "col_offset": 0,
+            "decorator_list": [],
+            "keywords": [],
+            "lineno": 23,
+            "name": "Response"
+        },
+        {
+            "_type": "ClassDef",
+            "bases": [
+                {
+                    "_type": "Name",
+                    "col_offset": 20,
+                    "ctx": {
+                        "_type": "Load"
+                    },
+                    "id": "DriverBase",
+                    "lineno": 36
+                }
+            ],
+            "body": [
+                {
+                    "_type": "AnnAssign",
+                    "annotation": {
+                        "_type": "Name",
+                        "col_offset": 12,
+                        "ctx": {
+                            "_type": "Load"
+                        },
+                        "id": "Buffer",
+                        "lineno": 37
+                    },
+                    "col_offset": 4,
+                    "lineno": 37,
+                    "simple": 1,
+                    "target": {
+                        "_type": "Name",
+                        "col_offset": 4,
+                        "ctx": {
+                            "_type": "Store"
+                        },
+                        "id": "buffer",
+                        "lineno": 37
+                    },
+                    "value": null
+                },
+                {
+                    "_type": "FunctionDef",
+                    "args": {
+                        "_type": "arguments",
+                        "args": [
+                            {
+                                "_type": "arg",
+                                "annotation": null,
+                                "arg": "self",
+                                "col_offset": 17,
+                                "lineno": 39
+                            },
+                            {
+                                "_type": "arg",
+                                "annotation": {
+                                    "_type": "Name",
+                                    "col_offset": 33,
+                                    "ctx": {
+                                        "_type": "Load"
+                                    },
+                                    "id": "Protocol",
+                                    "lineno": 39
+                                },
+                                "arg": "protocol",
+                                "col_offset": 23,
+                                "lineno": 39
+                            }
+                        ],
+                        "defaults": [],
+                        "kw_defaults": [],
+                        "kwarg": null,
+                        "kwonlyargs": [],
+                        "vararg": null
+                    },
+                    "body": [
+                        {
+                            "_type": "Expr",
+                            "col_offset": 8,
+                            "lineno": 40,
+                            "value": {
+                                "_type": "Call",
+                                "args": [
+                                    {
+                                        "_type": "Name",
+                                        "col_offset": 25,
+                                        "ctx": {
+                                            "_type": "Load"
+                                        },
+                                        "id": "protocol",
+                                        "lineno": 40
+                                    }
+                                ],
+                                "col_offset": 8,
+                                "func": {
+                                    "_type": "Attribute",
+                                    "attr": "__init__",
+                                    "col_offset": 8,
+                                    "ctx": {
+                                        "_type": "Load"
+                                    },
+                                    "lineno": 40,
+                                    "value": {
+                                        "_type": "Call",
+                                        "args": [],
+                                        "col_offset": 8,
+                                        "func": {
+                                            "_type": "Name",
+                                            "col_offset": 8,
+                                            "ctx": {
+                                                "_type": "Load"
+                                            },
+                                            "id": "super",
+                                            "lineno": 40
+                                        },
+                                        "keywords": [],
+                                        "lineno": 40
+                                    }
+                                },
+                                "keywords": [],
+                                "lineno": 40
+                            }
+                        }
+                    ],
+                    "col_offset": 4,
+                    "decorator_list": [],
+                    "lineno": 39,
+                    "name": "__init__",
+                    "returns": null
+                },
+                {
+                    "_type": "FunctionDef",
+                    "args": {
+                        "_type": "arguments",
+                        "args": [
+                            {
+                                "_type": "arg",
+                                "annotation": null,
+                                "arg": "self",
+                                "col_offset": 16,
+                                "lineno": 42
+                            }
+                        ],
+                        "defaults": [],
+                        "kw_defaults": [],
+                        "kwarg": null,
+                        "kwonlyargs": [],
+                        "vararg": null
+                    },
+                    "body": [
+                        {
+                            "_type": "Assign",
+                            "col_offset": 8,
+                            "lineno": 44,
+                            "targets": [
+                                {
+                                    "_type": "Attribute",
+                                    "attr": "buffer",
+                                    "col_offset": 8,
+                                    "ctx": {
+                                        "_type": "Store"
+                                    },
+                                    "lineno": 44,
+                                    "value": {
+                                        "_type": "Name",
+                                        "col_offset": 8,
+                                        "ctx": {
+                                            "_type": "Load"
+                                        },
+                                        "id": "self",
+                                        "lineno": 44
+                                    }
+                                }
+                            ],
+                            "value": {
+                                "_type": "Call",
+                                "args": [],
+                                "col_offset": 22,
+                                "func": {
+                                    "_type": "Attribute",
+                                    "attr": "connect",
+                                    "col_offset": 22,
+                                    "ctx": {
+                                        "_type": "Load"
+                                    },
+                                    "lineno": 44,
+                                    "value": {
+                                        "_type": "Attribute",
+                                        "attr": "protocol",
+                                        "col_offset": 22,
+                                        "ctx": {
+                                            "_type": "Load"
+                                        },
+                                        "lineno": 44,
+                                        "value": {
+                                            "_type": "Name",
+                                            "col_offset": 22,
+                                            "ctx": {
+                                                "_type": "Load"
+                                            },
+                                            "id": "self",
+                                            "lineno": 44
+                                        }
+                                    }
+                                },
+                                "keywords": [],
+                                "lineno": 44
+                            }
+                        },
+                        {
+                            "_type": "AnnAssign",
+                            "annotation": {
+                                "_type": "Name",
+                                "col_offset": 17,
+                                "ctx": {
+                                    "_type": "Load"
+                                },
+                                "id": "Request",
+                                "lineno": 46
+                            },
+                            "col_offset": 8,
+                            "lineno": 46,
+                            "simple": 1,
+                            "target": {
+                                "_type": "Name",
+                                "col_offset": 8,
+                                "ctx": {
+                                    "_type": "Store"
+                                },
+                                "id": "request",
+                                "lineno": 46
+                            },
+                            "value": {
+                                "_type": "Call",
+                                "args": [],
+                                "col_offset": 27,
+                                "func": {
+                                    "_type": "Name",
+                                    "col_offset": 27,
+                                    "ctx": {
+                                        "_type": "Load"
+                                    },
+                                    "id": "Request",
+                                    "lineno": 46
+                                },
+                                "keywords": [],
+                                "lineno": 46
+                            }
+                        },
+                        {
+                            "_type": "Expr",
+                            "col_offset": 8,
+                            "lineno": 48,
+                            "value": {
+                                "_type": "Call",
+                                "args": [
+                                    {
+                                        "_type": "Attribute",
+                                        "attr": "buffer",
+                                        "col_offset": 23,
+                                        "ctx": {
+                                            "_type": "Load"
+                                        },
+                                        "lineno": 48,
+                                        "value": {
+                                            "_type": "Name",
+                                            "col_offset": 23,
+                                            "ctx": {
+                                                "_type": "Load"
+                                            },
+                                            "id": "self",
+                                            "lineno": 48
+                                        }
+                                    }
+                                ],
+                                "col_offset": 8,
+                                "func": {
+                                    "_type": "Attribute",
+                                    "attr": "encode",
+                                    "col_offset": 8,
+                                    "ctx": {
+                                        "_type": "Load"
+                                    },
+                                    "lineno": 48,
+                                    "value": {
+                                        "_type": "Name",
+                                        "col_offset": 8,
+                                        "ctx": {
+                                            "_type": "Load"
+                                        },
+                                        "id": "request",
+                                        "lineno": 48
+                                    }
+                                },
+                                "keywords": [],
+                                "lineno": 48
+                            }
+                        },
+                        {
+                            "_type": "Expr",
+                            "col_offset": 8,
+                            "lineno": 51,
+                            "value": {
+                                "_type": "Call",
+                                "args": [
+                                    {
+                                        "_type": "Name",
+                                        "col_offset": 28,
+                                        "ctx": {
+                                            "_type": "Load"
+                                        },
+                                        "id": "Response",
+                                        "lineno": 51
+                                    }
+                                ],
+                                "col_offset": 8,
+                                "func": {
+                                    "_type": "Attribute",
+                                    "attr": "receive",
+                                    "col_offset": 8,
+                                    "ctx": {
+                                        "_type": "Load"
+                                    },
+                                    "lineno": 51,
+                                    "value": {
+                                        "_type": "Attribute",
+                                        "attr": "buffer",
+                                        "col_offset": 8,
+                                        "ctx": {
+                                            "_type": "Load"
+                                        },
+                                        "lineno": 51,
+                                        "value": {
+                                            "_type": "Name",
+                                            "col_offset": 8,
+                                            "ctx": {
+                                                "_type": "Load"
+                                            },
+                                            "id": "self",
+                                            "lineno": 51
+                                        }
+                                    }
+                                },
+                                "keywords": [],
+                                "lineno": 51
+                            }
+                        }
+                    ],
+                    "col_offset": 4,
+                    "decorator_list": [],
+                    "lineno": 42,
+                    "name": "connect",
+                    "returns": null
+                }
+            ],
+            "col_offset": 0,
+            "decorator_list": [],
+            "keywords": [],
+            "lineno": 36,
+            "name": "ExampleDriver"
+        },
+        {
+            "_type": "ClassDef",
+            "bases": [
+                {
+                    "_type": "Name",
+                    "col_offset": 18,
+                    "ctx": {
+                        "_type": "Load"
+                    },
+                    "id": "Buffer",
+                    "lineno": 54
+                }
+            ],
+            "body": [
+                {
+                    "_type": "FunctionDef",
+                    "args": {
+                        "_type": "arguments",
+                        "args": [
+                            {
+                                "_type": "arg",
+                                "annotation": null,
+                                "arg": "self",
+                                "col_offset": 17,
+                                "lineno": 56
+                            }
+                        ],
+                        "defaults": [],
+                        "kw_defaults": [],
+                        "kwarg": null,
+                        "kwonlyargs": [],
+                        "vararg": null
+                    },
+                    "body": [
+                        {
+                            "_type": "Return",
+                            "col_offset": 8,
+                            "lineno": 57,
+                            "value": {
+                                "_type": "Num",
+                                "col_offset": 15,
+                                "lineno": 57,
+                                "n": 0
+                            }
+                        }
+                    ],
+                    "col_offset": 4,
+                    "decorator_list": [],
+                    "lineno": 56,
+                    "name": "readByte",
+                    "returns": null
+                },
+                {
+                    "_type": "FunctionDef",
+                    "args": {
+                        "_type": "arguments",
+                        "args": [
+                            {
+                                "_type": "arg",
+                                "annotation": null,
+                                "arg": "self",
+                                "col_offset": 13,
+                                "lineno": 59
+                            },
+                            {
+                                "_type": "arg",
+                                "annotation": {
+                                    "_type": "Name",
+                                    "col_offset": 26,
+                                    "ctx": {
+                                        "_type": "Load"
+                                    },
+                                    "id": "bytearray",
+                                    "lineno": 59
+                                },
+                                "arg": "bytes",
+                                "col_offset": 19,
+                                "lineno": 59
+                            }
+                        ],
+                        "defaults": [],
+                        "kw_defaults": [],
+                        "kwarg": null,
+                        "kwonlyargs": [],
+                        "vararg": null
+                    },
+                    "body": [
+                        {
+                            "_type": "Expr",
+                            "col_offset": 8,
+                            "lineno": 60,
+                            "value": {
+                                "_type": "Call",
+                                "args": [
+                                    {
+                                        "_type": "Call",
+                                        "args": [
+                                            {
+                                                "_type": "Name",
+                                                "col_offset": 18,
+                                                "ctx": {
+                                                    "_type": "Load"
+                                                },
+                                                "id": "bytes",
+                                                "lineno": 60
+                                            }
+                                        ],
+                                        "col_offset": 14,
+                                        "func": {
+                                            "_type": "Name",
+                                            "col_offset": 14,
+                                            "ctx": {
+                                                "_type": "Load"
+                                            },
+                                            "id": "str",
+                                            "lineno": 60
+                                        },
+                                        "keywords": [],
+                                        "lineno": 60
+                                    }
+                                ],
+                                "col_offset": 8,
+                                "func": {
+                                    "_type": "Name",
+                                    "col_offset": 8,
+                                    "ctx": {
+                                        "_type": "Load"
+                                    },
+                                    "id": "print",
+                                    "lineno": 60
+                                },
+                                "keywords": [],
+                                "lineno": 60
+                            }
+                        }
+                    ],
+                    "col_offset": 4,
+                    "decorator_list": [],
+                    "lineno": 59,
+                    "name": "send",
+                    "returns": null
+                },
+                {
+                    "_type": "FunctionDef",
+                    "args": {
+                        "_type": "arguments",
+                        "args": [
+                            {
+                                "_type": "arg",
+                                "annotation": null,
+                                "arg": "self",
+                                "col_offset": 16,
+                                "lineno": 62
+                            },
+                            {
+                                "_type": "arg",
+                                "annotation": {
+                                    "_type": "Name",
+                                    "col_offset": 32,
+                                    "ctx": {
+                                        "_type": "Load"
+                                    },
+                                    "id": "type",
+                                    "lineno": 62
+                                },
+                                "arg": "response",
+                                "col_offset": 22,
+                                "lineno": 62
+                            }
+                        ],
+                        "defaults": [],
+                        "kw_defaults": [],
+                        "kwarg": null,
+                        "kwonlyargs": [],
+                        "vararg": null
+                    },
+                    "body": [
+                        {
+                            "_type": "Return",
+                            "col_offset": 8,
+                            "lineno": 63,
+                            "value": {
+                                "_type": "Call",
+                                "args": [
+                                    {
+                                        "_type": "Name",
+                                        "col_offset": 31,
+                                        "ctx": {
+                                            "_type": "Load"
+                                        },
+                                        "id": "self",
+                                        "lineno": 63
+                                    }
+                                ],
+                                "col_offset": 15,
+                                "func": {
+                                    "_type": "Attribute",
+                                    "attr": "decode",
+                                    "col_offset": 15,
+                                    "ctx": {
+                                        "_type": "Load"
+                                    },
+                                    "lineno": 63,
+                                    "value": {
+                                        "_type": "Name",
+                                        "col_offset": 15,
+                                        "ctx": {
+                                            "_type": "Load"
+                                        },
+                                        "id": "response",
+                                        "lineno": 63
+                                    }
+                                },
+                                "keywords": [],
+                                "lineno": 63
+                            }
+                        }
+                    ],
+                    "col_offset": 4,
+                    "decorator_list": [],
+                    "lineno": 62,
+                    "name": "receive",
+                    "returns": null
+                }
+            ],
+            "col_offset": 0,
+            "decorator_list": [],
+            "keywords": [],
+            "lineno": 54,
+            "name": "DummyBuffer"
+        },
+        {
+            "_type": "ClassDef",
+            "bases": [
+                {
+                    "_type": "Name",
+                    "col_offset": 20,
+                    "ctx": {
+                        "_type": "Load"
+                    },
+                    "id": "Protocol",
+                    "lineno": 66
+                }
+            ],
+            "body": [
+                {
+                    "_type": "FunctionDef",
+                    "args": {
+                        "_type": "arguments",
+                        "args": [
+                            {
+                                "_type": "arg",
+                                "annotation": null,
+                                "arg": "self",
+                                "col_offset": 16,
+                                "lineno": 68
+                            }
+                        ],
+                        "defaults": [],
+                        "kw_defaults": [],
+                        "kwarg": null,
+                        "kwonlyargs": [],
+                        "vararg": null
+                    },
+                    "body": [
+                        {
+                            "_type": "Return",
+                            "col_offset": 8,
+                            "lineno": 69,
+                            "value": {
+                                "_type": "Call",
+                                "args": [],
+                                "col_offset": 15,
+                                "func": {
+                                    "_type": "Name",
+                                    "col_offset": 15,
+                                    "ctx": {
+                                        "_type": "Load"
+                                    },
+                                    "id": "DummyBuffer",
+                                    "lineno": 69
+                                },
+                                "keywords": [],
+                                "lineno": 69
+                            }
+                        }
+                    ],
+                    "col_offset": 4,
+                    "decorator_list": [],
+                    "lineno": 68,
+                    "name": "connect",
+                    "returns": {
+                        "_type": "Name",
+                        "col_offset": 25,
+                        "ctx": {
+                            "_type": "Load"
+                        },
+                        "id": "Buffer",
+                        "lineno": 68
+                    }
+                },
+                {
+                    "_type": "FunctionDef",
+                    "args": {
+                        "_type": "arguments",
+                        "args": [
+                            {
+                                "_type": "arg",
+                                "annotation": null,
+                                "arg": "self",
+                                "col_offset": 14,
+                                "lineno": 71
+                            }
+                        ],
+                        "defaults": [],
+                        "kw_defaults": [],
+                        "kwarg": null,
+                        "kwonlyargs": [],
+                        "vararg": null
+                    },
+                    "body": [
+                        {
+                            "_type": "Pass",
+                            "col_offset": 8,
+                            "lineno": 72
+                        }
+                    ],
+                    "col_offset": 4,
+                    "decorator_list": [],
+                    "lineno": 71,
+                    "name": "close",
+                    "returns": null
+                }
+            ],
+            "col_offset": 0,
+            "decorator_list": [],
+            "keywords": [],
+            "lineno": 66,
+            "name": "DummyProtocol"
+        },
+        {
+            "_type": "If",
+            "body": [
+                {
+                    "_type": "Assign",
+                    "col_offset": 4,
+                    "lineno": 77,
+                    "targets": [
+                        {
+                            "_type": "Name",
+                            "col_offset": 4,
+                            "ctx": {
+                                "_type": "Store"
+                            },
+                            "id": "store",
+                            "lineno": 77
+                        }
+                    ],
+                    "value": {
+                        "_type": "Call",
+                        "args": [],
+                        "col_offset": 12,
+                        "func": {
+                            "_type": "Name",
+                            "col_offset": 12,
+                            "ctx": {
+                                "_type": "Load"
+                            },
+                            "id": "ModbusSlaveContext",
+                            "lineno": 77
+                        },
+                        "keywords": [
+                            {
+                                "_type": "keyword",
+                                "arg": "di",
+                                "value": {
+                                    "_type": "Call",
+                                    "args": [
+                                        {
+                                            "_type": "Num",
+                                            "col_offset": 37,
+                                            "lineno": 78,
+                                            "n": 0
+                                        },
+                                        {
+                                            "_type": "BinOp",
+                                            "col_offset": 40,
+                                            "left": {
+                                                "_type": "List",
+                                                "col_offset": 40,
+                                                "ctx": {
+                                                    "_type": "Load"
+                                                },
+                                                "elts": [
+                                                    {
+                                                        "_type": "Num",
+                                                        "col_offset": 41,
+                                                        "lineno": 78,
+                                                        "n": 17
+                                                    }
+                                                ],
+                                                "lineno": 78
+                                            },
+                                            "lineno": 78,
+                                            "op": {
+                                                "_type": "Mult"
+                                            },
+                                            "right": {
+                                                "_type": "Num",
+                                                "col_offset": 47,
+                                                "lineno": 78,
+                                                "n": 100
+                                            }
+                                        }
+                                    ],
+                                    "col_offset": 11,
+                                    "func": {
+                                        "_type": "Name",
+                                        "col_offset": 11,
+                                        "ctx": {
+                                            "_type": "Load"
+                                        },
+                                        "id": "ModbusSequentialDataBlock",
+                                        "lineno": 78
+                                    },
+                                    "keywords": [],
+                                    "lineno": 78
+                                }
+                            },
+                            {
+                                "_type": "keyword",
+                                "arg": "co",
+                                "value": {
+                                    "_type": "Call",
+                                    "args": [
+                                        {
+                                            "_type": "Num",
+                                            "col_offset": 37,
+                                            "lineno": 79,
+                                            "n": 0
+                                        },
+                                        {
+                                            "_type": "BinOp",
+                                            "col_offset": 40,
+                                            "left": {
+                                                "_type": "List",
+                                                "col_offset": 40,
+                                                "ctx": {
+                                                    "_type": "Load"
+                                                },
+                                                "elts": [
+                                                    {
+                                                        "_type": "Num",
+                                                        "col_offset": 41,
+                                                        "lineno": 79,
+                                                        "n": 17
+                                                    }
+                                                ],
+                                                "lineno": 79
+                                            },
+                                            "lineno": 79,
+                                            "op": {
+                                                "_type": "Mult"
+                                            },
+                                            "right": {
+                                                "_type": "Num",
+                                                "col_offset": 47,
+                                                "lineno": 79,
+                                                "n": 100
+                                            }
+                                        }
+                                    ],
+                                    "col_offset": 11,
+                                    "func": {
+                                        "_type": "Name",
+                                        "col_offset": 11,
+                                        "ctx": {
+                                            "_type": "Load"
+                                        },
+                                        "id": "ModbusSequentialDataBlock",
+                                        "lineno": 79
+                                    },
+                                    "keywords": [],
+                                    "lineno": 79
+                                }
+                            },
+                            {
+                                "_type": "keyword",
+                                "arg": "hr",
+                                "value": {
+                                    "_type": "Call",
+                                    "args": [
+                                        {
+                                            "_type": "Num",
+                                            "col_offset": 37,
+                                            "lineno": 80,
+                                            "n": 0
+                                        },
+                                        {
+                                            "_type": "BinOp",
+                                            "col_offset": 40,
+                                            "left": {
+                                                "_type": "List",
+                                                "col_offset": 40,
+                                                "ctx": {
+                                                    "_type": "Load"
+                                                },
+                                                "elts": [
+                                                    {
+                                                        "_type": "Num",
+                                                        "col_offset": 41,
+                                                        "lineno": 80,
+                                                        "n": 17
+                                                    }
+                                                ],
+                                                "lineno": 80
+                                            },
+                                            "lineno": 80,
+                                            "op": {
+                                                "_type": "Mult"
+                                            },
+                                            "right": {
+                                                "_type": "Num",
+                                                "col_offset": 47,
+                                                "lineno": 80,
+                                                "n": 100
+                                            }
+                                        }
+                                    ],
+                                    "col_offset": 11,
+                                    "func": {
+                                        "_type": "Name",
+                                        "col_offset": 11,
+                                        "ctx": {
+                                            "_type": "Load"
+                                        },
+                                        "id": "ModbusSequentialDataBlock",
+                                        "lineno": 80
+                                    },
+                                    "keywords": [],
+                                    "lineno": 80
+                                }
+                            },
+                            {
+                                "_type": "keyword",
+                                "arg": "ir",
+                                "value": {
+                                    "_type": "Call",
+                                    "args": [
+                                        {
+                                            "_type": "Num",
+                                            "col_offset": 37,
+                                            "lineno": 81,
+                                            "n": 0
+                                        },
+                                        {
+                                            "_type": "BinOp",
+                                            "col_offset": 40,
+                                            "left": {
+                                                "_type": "List",
+                                                "col_offset": 40,
+                                                "ctx": {
+                                                    "_type": "Load"
+                                                },
+                                                "elts": [
+                                                    {
+                                                        "_type": "Num",
+                                                        "col_offset": 41,
+                                                        "lineno": 81,
+                                                        "n": 17
+                                                    }
+                                                ],
+                                                "lineno": 81
+                                            },
+                                            "lineno": 81,
+                                            "op": {
+                                                "_type": "Mult"
+                                            },
+                                            "right": {
+                                                "_type": "Num",
+                                                "col_offset": 47,
+                                                "lineno": 81,
+                                                "n": 100
+                                            }
+                                        }
+                                    ],
+                                    "col_offset": 11,
+                                    "func": {
+                                        "_type": "Name",
+                                        "col_offset": 11,
+                                        "ctx": {
+                                            "_type": "Load"
+                                        },
+                                        "id": "ModbusSequentialDataBlock",
+                                        "lineno": 81
+                                    },
+                                    "keywords": [],
+                                    "lineno": 81
+                                }
+                            }
+                        ],
+                        "lineno": 77
+                    }
+                },
+                {
+                    "_type": "Assign",
+                    "col_offset": 4,
+                    "lineno": 83,
+                    "targets": [
+                        {
+                            "_type": "Name",
+                            "col_offset": 4,
+                            "ctx": {
+                                "_type": "Store"
+                            },
+                            "id": "context",
+                            "lineno": 83
+                        }
+                    ],
+                    "value": {
+                        "_type": "Call",
+                        "args": [],
+                        "col_offset": 14,
+                        "func": {
+                            "_type": "Name",
+                            "col_offset": 14,
+                            "ctx": {
+                                "_type": "Load"
+                            },
+                            "id": "ModbusServerContext",
+                            "lineno": 83
+                        },
+                        "keywords": [
+                            {
+                                "_type": "keyword",
+                                "arg": "slaves",
+                                "value": {
+                                    "_type": "Name",
+                                    "col_offset": 41,
+                                    "ctx": {
+                                        "_type": "Load"
+                                    },
+                                    "id": "store",
+                                    "lineno": 83
+                                }
+                            },
+                            {
+                                "_type": "keyword",
+                                "arg": "single",
+                                "value": {
+                                    "_type": "NameConstant",
+                                    "col_offset": 55,
+                                    "lineno": 83,
+                                    "value": true
+                                }
+                            }
+                        ],
+                        "lineno": 83
+                    }
+                },
+                {
+                    "_type": "Assign",
+                    "col_offset": 4,
+                    "lineno": 90,
+                    "targets": [
+                        {
+                            "_type": "Name",
+                            "col_offset": 4,
+                            "ctx": {
+                                "_type": "Store"
+                            },
+                            "id": "identity",
+                            "lineno": 90
+                        }
+                    ],
+                    "value": {
+                        "_type": "Call",
+                        "args": [],
+                        "col_offset": 15,
+                        "func": {
+                            "_type": "Name",
+                            "col_offset": 15,
+                            "ctx": {
+                                "_type": "Load"
+                            },
+                            "id": "ModbusDeviceIdentification",
+                            "lineno": 90
+                        },
+                        "keywords": [],
+                        "lineno": 90
+                    }
+                },
+                {
+                    "_type": "Assign",
+                    "col_offset": 4,
+                    "lineno": 91,
+                    "targets": [
+                        {
+                            "_type": "Attribute",
+                            "attr": "VendorName",
+                            "col_offset": 4,
+                            "ctx": {
+                                "_type": "Store"
+                            },
+                            "lineno": 91,
+                            "value": {
+                                "_type": "Name",
+                                "col_offset": 4,
+                                "ctx": {
+                                    "_type": "Load"
+                                },
+                                "id": "identity",
+                                "lineno": 91
+                            }
+                        }
+                    ],
+                    "value": {
+                        "_type": "Str",
+                        "col_offset": 26,
+                        "lineno": 91,
+                        "s": "Pymodbus"
+                    }
+                },
+                {
+                    "_type": "Assign",
+                    "col_offset": 4,
+                    "lineno": 92,
+                    "targets": [
+                        {
+                            "_type": "Attribute",
+                            "attr": "ProductCode",
+                            "col_offset": 4,
+                            "ctx": {
+                                "_type": "Store"
+                            },
+                            "lineno": 92,
+                            "value": {
+                                "_type": "Name",
+                                "col_offset": 4,
+                                "ctx": {
+                                    "_type": "Load"
+                                },
+                                "id": "identity",
+                                "lineno": 92
+                            }
+                        }
+                    ],
+                    "value": {
+                        "_type": "Str",
+                        "col_offset": 27,
+                        "lineno": 92,
+                        "s": "PM"
+                    }
+                },
+                {
+                    "_type": "Assign",
+                    "col_offset": 4,
+                    "lineno": 93,
+                    "targets": [
+                        {
+                            "_type": "Attribute",
+                            "attr": "VendorUrl",
+                            "col_offset": 4,
+                            "ctx": {
+                                "_type": "Store"
+                            },
+                            "lineno": 93,
+                            "value": {
+                                "_type": "Name",
+                                "col_offset": 4,
+                                "ctx": {
+                                    "_type": "Load"
+                                },
+                                "id": "identity",
+                                "lineno": 93
+                            }
+                        }
+                    ],
+                    "value": {
+                        "_type": "Str",
+                        "col_offset": 25,
+                        "lineno": 93,
+                        "s": "http://github.com/riptideio/pymodbus/"
+                    }
+                },
+                {
+                    "_type": "Assign",
+                    "col_offset": 4,
+                    "lineno": 94,
+                    "targets": [
+                        {
+                            "_type": "Attribute",
+                            "attr": "ProductName",
+                            "col_offset": 4,
+                            "ctx": {
+                                "_type": "Store"
+                            },
+                            "lineno": 94,
+                            "value": {
+                                "_type": "Name",
+                                "col_offset": 4,
+                                "ctx": {
+                                    "_type": "Load"
+                                },
+                                "id": "identity",
+                                "lineno": 94
+                            }
+                        }
+                    ],
+                    "value": {
+                        "_type": "Str",
+                        "col_offset": 27,
+                        "lineno": 94,
+                        "s": "Pymodbus Server"
+                    }
+                },
+                {
+                    "_type": "Assign",
+                    "col_offset": 4,
+                    "lineno": 95,
+                    "targets": [
+                        {
+                            "_type": "Attribute",
+                            "attr": "ModelName",
+                            "col_offset": 4,
+                            "ctx": {
+                                "_type": "Store"
+                            },
+                            "lineno": 95,
+                            "value": {
+                                "_type": "Name",
+                                "col_offset": 4,
+                                "ctx": {
+                                    "_type": "Load"
+                                },
+                                "id": "identity",
+                                "lineno": 95
+                            }
+                        }
+                    ],
+                    "value": {
+                        "_type": "Str",
+                        "col_offset": 25,
+                        "lineno": 95,
+                        "s": "Pymodbus Server"
+                    }
+                },
+                {
+                    "_type": "Assign",
+                    "col_offset": 4,
+                    "lineno": 96,
+                    "targets": [
+                        {
+                            "_type": "Attribute",
+                            "attr": "MajorMinorRevision",
+                            "col_offset": 4,
+                            "ctx": {
+                                "_type": "Store"
+                            },
+                            "lineno": 96,
+                            "value": {
+                                "_type": "Name",
+                                "col_offset": 4,
+                                "ctx": {
+                                    "_type": "Load"
+                                },
+                                "id": "identity",
+                                "lineno": 96
+                            }
+                        }
+                    ],
+                    "value": {
+                        "_type": "Str",
+                        "col_offset": 34,
+                        "lineno": 96,
+                        "s": "2.1.0"
+                    }
+                },
+                {
+                    "_type": "Assign",
+                    "col_offset": 4,
+                    "lineno": 102,
+                    "targets": [
+                        {
+                            "_type": "Name",
+                            "col_offset": 4,
+                            "ctx": {
+                                "_type": "Store"
+                            },
+                            "id": "server",
+                            "lineno": 102
+                        }
+                    ],
+                    "value": {
+                        "_type": "Call",
+                        "args": [
+                            {
+                                "_type": "Name",
+                                "col_offset": 29,
+                                "ctx": {
+                                    "_type": "Load"
+                                },
+                                "id": "context",
+                                "lineno": 102
+                            }
+                        ],
+                        "col_offset": 13,
+                        "func": {
+                            "_type": "Name",
+                            "col_offset": 13,
+                            "ctx": {
+                                "_type": "Load"
+                            },
+                            "id": "ModbusTcpServer",
+                            "lineno": 102
+                        },
+                        "keywords": [
+                            {
+                                "_type": "keyword",
+                                "arg": "identity",
+                                "value": {
+                                    "_type": "Name",
+                                    "col_offset": 47,
+                                    "ctx": {
+                                        "_type": "Load"
+                                    },
+                                    "id": "identity",
+                                    "lineno": 102
+                                }
+                            },
+                            {
+                                "_type": "keyword",
+                                "arg": "address",
+                                "value": {
+                                    "_type": "Tuple",
+                                    "col_offset": 66,
+                                    "ctx": {
+                                        "_type": "Load"
+                                    },
+                                    "elts": [
+                                        {
+                                            "_type": "Str",
+                                            "col_offset": 66,
+                                            "lineno": 102,
+                                            "s": "localhost"
+                                        },
+                                        {
+                                            "_type": "Num",
+                                            "col_offset": 79,
+                                            "lineno": 102,
+                                            "n": 5020
+                                        }
+                                    ],
+                                    "lineno": 102
+                                }
+                            }
+                        ],
+                        "lineno": 102
+                    }
+                },
+                {
+                    "_type": "Assign",
+                    "col_offset": 4,
+                    "lineno": 104,
+                    "targets": [
+                        {
+                            "_type": "Name",
+                            "col_offset": 4,
+                            "ctx": {
+                                "_type": "Store"
+                            },
+                            "id": "drv",
+                            "lineno": 104
+                        }
+                    ],
+                    "value": {
+                        "_type": "Call",
+                        "args": [
+                            {
+                                "_type": "Call",
+                                "args": [],
+                                "col_offset": 24,
+                                "func": {
+                                    "_type": "Name",
+                                    "col_offset": 24,
+                                    "ctx": {
+                                        "_type": "Load"
+                                    },
+                                    "id": "DummyProtocol",
+                                    "lineno": 104
+                                },
+                                "keywords": [],
+                                "lineno": 104
+                            }
+                        ],
+                        "col_offset": 10,
+                        "func": {
+                            "_type": "Name",
+                            "col_offset": 10,
+                            "ctx": {
+                                "_type": "Load"
+                            },
+                            "id": "ExampleDriver",
+                            "lineno": 104
+                        },
+                        "keywords": [],
+                        "lineno": 104
+                    }
+                },
+                {
+                    "_type": "Expr",
+                    "col_offset": 4,
+                    "lineno": 105,
+                    "value": {
+                        "_type": "Call",
+                        "args": [],
+                        "col_offset": 4,
+                        "func": {
+                            "_type": "Attribute",
+                            "attr": "connect",
+                            "col_offset": 4,
+                            "ctx": {
+                                "_type": "Load"
+                            },
+                            "lineno": 105,
+                            "value": {
+                                "_type": "Name",
+                                "col_offset": 4,
+                                "ctx": {
+                                    "_type": "Load"
+                                },
+                                "id": "drv",
+                                "lineno": 105
+                            }
+                        },
+                        "keywords": [],
+                        "lineno": 105
+                    }
+                },
+                {
+                    "_type": "Expr",
+                    "col_offset": 4,
+                    "lineno": 107,
+                    "value": {
+                        "_type": "Call",
+                        "args": [],
+                        "col_offset": 4,
+                        "func": {
+                            "_type": "Attribute",
+                            "attr": "server_close",
+                            "col_offset": 4,
+                            "ctx": {
+                                "_type": "Load"
+                            },
+                            "lineno": 107,
+                            "value": {
+                                "_type": "Name",
+                                "col_offset": 4,
+                                "ctx": {
+                                    "_type": "Load"
+                                },
+                                "id": "server",
+                                "lineno": 107
+                            }
+                        },
+                        "keywords": [],
+                        "lineno": 107
+                    }
+                }
+            ],
+            "col_offset": 0,
+            "lineno": 75,
+            "orelse": [],
+            "test": {
+                "_type": "Compare",
+                "col_offset": 3,
+                "comparators": [
+                    {
+                        "_type": "Str",
+                        "col_offset": 15,
+                        "lineno": 75,
+                        "s": "__main__"
+                    }
+                ],
+                "left": {
+                    "_type": "Name",
+                    "col_offset": 3,
+                    "ctx": {
+                        "_type": "Load"
+                    },
+                    "id": "__name__",
+                    "lineno": 75
+                },
+                "lineno": 75,
+                "ops": [
+                    {
+                        "_type": "Eq"
+                    }
+                ]
+            }
+        }
+    ]
+}
\ No newline at end of file
diff --git a/sandbox/code-gen/src/test/java/org/apache/plc4x/codegen/ModuleNodeTest.java b/sandbox/code-gen/src/test/java/org/apache/plc4x/codegen/ModuleNodeTest.java
new file mode 100644
index 0000000..1ba9fa3
--- /dev/null
+++ b/sandbox/code-gen/src/test/java/org/apache/plc4x/codegen/ModuleNodeTest.java
@@ -0,0 +1,170 @@
+package org.apache.plc4x.codegen;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.platform.commons.util.Preconditions;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+
+import static org.junit.Assert.assertTrue;
+
+class ModuleNodeTest {
+
+    private ObjectMapper mapper;
+
+    @BeforeEach
+    void setUp() {
+        mapper = new ObjectMapper();
+        mapper.registerSubtypes(ModuleNode.class);
+        mapper.registerSubtypes(ClassDefNode.class);
+        mapper.registerSubtypes(PassNode.class);
+        mapper.registerSubtypes(FunctionDefNode.class);
+        mapper.registerSubtypes(ArgumentsNode.class);
+        mapper.registerSubtypes(ExprNode.class);
+        mapper.registerSubtypes(CallNode.class);
+        mapper.registerSubtypes(StrNode.class);
+        mapper.registerSubtypes(NameNode.class);
+        mapper.registerSubtypes(LoadNode.class);
+        mapper.registerSubtypes(AnnAssignerNode.class);
+        mapper.registerSubtypes(StoreNode.class);
+        mapper.registerSubtypes(NumNode.class);
+        mapper.registerSubtypes(AugAssignNode.class);
+        mapper.registerSubtypes(AddNode.class);
+        mapper.registerSubtypes(ImportFromNode.class);
+        mapper.registerSubtypes(AliasNode.class);
+        mapper.registerSubtypes(ArgNode.class);
+        mapper.registerSubtypes(AssignNode.class);
+        mapper.registerSubtypes(AttributeNode.class);
+        mapper.registerSubtypes(WhileNode.class);
+        mapper.registerSubtypes(CompareNode.class);
+        mapper.registerSubtypes(NotEqNode.class);
+        mapper.registerSubtypes(ReturnNode.class);
+        mapper.registerSubtypes(IfNode.class);
+        mapper.registerSubtypes(KeywordNode.class);
+        mapper.registerSubtypes(BinOpNode.class);
+        mapper.registerSubtypes(ListNode.class);
+        mapper.registerSubtypes(MultNode.class);
+        mapper.registerSubtypes(NameConstantNode.class);
+        mapper.registerSubtypes(TupleNode.class);
+        mapper.registerSubtypes(EqNode.class);
+    }
+
+    @Test
+    void serialize() throws IOException {
+        final ModuleNode node = new ModuleNode();
+        node.setBody(Collections.singletonList(new ClassDefNode()));
+
+        final String s = mapper.writeValueAsString(node);
+
+        System.out.println(s);
+
+        // Reread
+        final Node root = mapper.readValue(s, Node.class);
+
+        System.out.println(root);
+    }
+
+    @Test
+    void deserializeExample() throws IOException {
+        final Node root = mapper.readValue(new File("src/main/resources/example.json"), Node.class);
+
+        assertTrue(root instanceof ModuleNode);
+        assertTrue(((ModuleNode) root).getBody().get(0) instanceof ClassDefNode);
+
+        // Print the node again
+        System.out.println(mapper.writeValueAsString(root));
+    }
+
+    @Test
+    void deserializeExample2() throws IOException {
+        final Node root = mapper.readValue(new File("src/main/resources/example2.json"), Node.class);
+
+        assertTrue(root instanceof ModuleNode);
+
+        // Print the node again
+        System.out.println(mapper.writeValueAsString(root));
+    }
+
+    @Test
+    void visitMinimalTree() throws IOException {
+        final Node root = mapper.readValue(new File("src/main/resources/example2.json"), Node.class);
+
+        CodePrinter printer = new CodePrinter(4);
+
+        NodeVisitor<String> toString = new AbstractNodeVisitor<String>() {
+
+
+            @Override public String visit(CompareNode compareNode) {
+                assert compareNode.getComparators().size() == 1;
+                return compareNode.getLeft().accept(this) + " " + compareNode.getOps().get(0).accept(this) + " " + compareNode.getComparators().get(0).accept(this);
+            }
+
+            @Override public String visit(EqNode eqNode) {
+                return "==";
+            }
+
+            @Override public String visit(NotEqNode notEqNode) {
+                return "!=";
+            }
+
+            @Override public String visit(NumNode numNode) {
+                return Double.toString(numNode.getN());
+            }
+
+            @Override public String visit(StrNode strNode) {
+                return strNode.getS();
+            }
+
+            @Override public String visit(NameNode nameNode) {
+                return nameNode.getId();
+            }
+
+            @Override public String visit(AttributeNode attributeNode) {
+                return attributeNode.getAttr();
+            }
+
+            @Override public String visit(CallNode callNode) {
+                final String function = callNode.getFunc().accept(this);
+
+                String s = function + "(";
+                for (Node arg : callNode.getArgs()) {
+                    s += arg.accept(this) + ", ";
+                }
+                for (Node keyword : callNode.getKeywords()) {
+                    s += keyword.accept(this);
+                }
+                s += ")";
+                return s;
+            }
+
+            @Override public String visit(KeywordNode keywordNode) {
+                return keywordNode.getArg() + " = " + keywordNode.getValue().accept(this);
+            }
+
+            @Override public String visit(AssignNode assignNode) {
+                assert assignNode.getTargets().size() == 1;
+                printer.writeLine(String.format("%s = %s;", assignNode.getTargets().get(0).accept(this), assignNode.getValue().accept(this))); ;
+                return super.visit(assignNode);
+            }
+
+            @Override public String visit(IfNode ifNode) {
+                printer.writeLine(String.format("If (%s) {", ifNode.getTest().accept(this)));
+                printer.startBlock();
+                for (Node node : ifNode.getBody()) {
+                    node.accept(this);
+                }
+                printer.endBlock();
+                printer.writeLine("}");
+                return null;
+            }
+        };
+
+
+        root.accept(toString);
+
+        System.out.println(printer.getCode());
+    }
+}
\ No newline at end of file
diff --git a/sandbox/pom.xml b/sandbox/pom.xml
index bf2effd..2d4ddf1 100644
--- a/sandbox/pom.xml
+++ b/sandbox/pom.xml
@@ -37,6 +37,7 @@
   <modules>
     <module>dynamic-driver-base</module>
     <module>dynamic-driver-s7</module>
+    <module>code-gen</module>
   </modules>
 
 </project>
\ No newline at end of file