Commit c13af36f authored by Philip Makedonski's avatar Philip Makedonski
Browse files

+ handle extensions and reductions in TTCN-3 renderer, &27

+ add length to reserved keywords
parent 9ae24ef2
Loading
Loading
Loading
Loading
Loading
+82 −10
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@ package org.etsi.mts.tdl.tools.rt.renderers;
import org.etsi.mts.tdl.Package;
import org.etsi.mts.tdl.PackageableElement;
import org.etsi.mts.tdl.Parameter;
import org.etsi.mts.tdl.ParameterBinding;
import org.etsi.mts.tdl.PredefinedFunctionCall;
import org.etsi.mts.tdl.SimpleDataInstance;
import org.etsi.mts.tdl.SimpleDataType;
@@ -21,6 +22,7 @@ import org.etsi.mts.tdl.VerdictAssignment;
import java.util.List;
import java.util.stream.Collectors;

import org.eclipse.xtext.EcoreUtil2;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.etsi.mts.tdl.Action;
import org.etsi.mts.tdl.ActionReference;
@@ -36,6 +38,7 @@ import org.etsi.mts.tdl.Behaviour;
import org.etsi.mts.tdl.Block;
import org.etsi.mts.tdl.BoundedLoopBehaviour;
import org.etsi.mts.tdl.Break;
import org.etsi.mts.tdl.CastDataUse;
import org.etsi.mts.tdl.CollectionDataInstance;
import org.etsi.mts.tdl.CollectionDataType;
import org.etsi.mts.tdl.ComponentInstance;
@@ -58,7 +61,7 @@ import org.etsi.mts.tdl.OmitValue;

public class TTCN3Renderer {
	private List<String> binaryFunctions = List.of("+", "-", "*", "/", "mod", "or", "and", "xor", "!=", "<", ">", "<=", ">=", "==");
	private List<String> keywords = List.of("message", "port", "value");
	private List<String> keywords = List.of("message", "port", "value", "length");
	private String indent = "  ";
	private String LF = "\n";
	
@@ -129,15 +132,43 @@ public class TTCN3Renderer {
		String output = "";
		//TODO: handle union, etc?
		output+=indent+"type record "+ttcnName(e)+" {"+LF;
		//TODO: handle extensions?
		//TODO: handle extensions? -> use union for super type with subtypes as fields?
		output+=e.allMembers().stream()
			.map(m -> indent+this.indent+ttcnName(m.getDataType())+" "+ttcnName(m)+optional(m))
			.collect(Collectors.joining(",\n"))+LF;
			.collect(Collectors.joining(","+LF))+LF;
		
		output+=renderExtensions(e, indent);
		output+=indent+"}"+LF;
		return output;
	}

	String renderExtensions(StructuredDataType e, String indent) {
		String output = "";
		List<StructuredDataType> extensions = EcoreUtil2.getAllContentsOfType(e.eResource(), StructuredDataType.class).stream()
//			.map(t -> t.getExtension())
//			.flatMap(t -> t.stream())
//			.filter(t -> t.getExtending() == e)
//			.map(t -> (StructuredDataType)t.getExtending())
			.filter(t -> t.getExtension().stream().anyMatch(x -> x.getExtending() == e))
			.toList();
		if (!extensions.isEmpty()) {
			output+=indent+this.indent+"union {"+LF;
			output+=extensions.stream().map(x -> renderExtension(x, indent+this.indent+this.indent)).collect(Collectors.joining(","+LF))+LF;
			output+=indent+this.indent+"} extensions optional"+LF;
		}
		return output;
	}

	private String renderExtension(StructuredDataType t, String indent) {
		String output = "";
		output+=indent+"record {"+LF;
		output+=t.allMembers().stream()
				.map(m -> indent+this.indent+ttcnName(m.getDataType())+" "+ttcnName(m)+optional(m))
				.collect(Collectors.joining(","+LF))+LF;
		output+=indent+"} "+ttcnName(t);
		return output;
	}
	
	String optional(Member m) {
		return m.isIsOptional() ? " optional" : "";
	}
@@ -147,13 +178,12 @@ public class TTCN3Renderer {
		output+=indent+"template "+ttcnName(e.getDataType())+" "+ttcnName(e)+" := {"+LF;
		//TODO: unassigned
		output+=e.getMemberAssignment().stream()
				.map(m -> indent+this.indent+ttcnName(m.getMember())+" := "+render(m.getMemberSpec(), indent))
				.map(m -> indent+this.indent+ttcnName(m.getMember())+" := "+render(m.getMember(), m.getMemberSpec(), indent))
				.collect(Collectors.joining(",\n"))+LF;
		output+=indent+"}"+LF;
		return output;
	}


	String render(SimpleDataInstance e, String indent) {
		String output = "";
		output+=indent+"template "+ttcnName(e.getDataType())+" "+ttcnName(e)+" := \""+ttcnName(e)+"\";"+LF;
@@ -202,7 +232,9 @@ public class TTCN3Renderer {
				.collect(Collectors.joining(","));
		output+=indent+"function "+ttcnName(e)+" ("+parameter+") return "+ttcnName(e.getReturnType())+"{"+LF;
		output+=indent+this.indent+"/* "+LF;
		if (e.getBody()!=null) {
			output+=indent+this.indent+e.getBody()+LF;
		}
		output+=indent+this.indent+"*/"+LF;
		output+=indent+"}"+LF;
		return output;
@@ -228,9 +260,11 @@ public class TTCN3Renderer {
			case AnyValue u -> "?";
			case AnyValueOrOmit u -> "*";
			case OmitValue u -> "omit";
			case CastDataUse u -> render(u, indent);
			case PredefinedFunctionCall u -> render(u, indent);
			default -> renderUnsupported(e, indent);
		};
		}
		;
	}

	String render(DataElementUse e, String indent) {
@@ -240,15 +274,15 @@ public class TTCN3Renderer {
			//TODO: anonymous types
			//TODO: with or without parameters, {} vs ()
			String arguments =e.getArgument().stream()
					.map(m -> render(m.getDataUse(), indent+this.indent))
					.map(m -> render(m.getDataUse(), ""))
					.collect(Collectors.joining(", "));
			String assignedArguments =e.getArgument().stream()
					.map(m -> ttcnName(m.getParameter())+" := "+render(m.getDataUse(), indent+this.indent))
					.map(m -> ttcnName(m.getParameter())+" := "+render(m.getParameter(), m.getDataUse(), ""))
					.collect(Collectors.joining(", "));

			NamedElement dataElement = e.getDataElement();
			output+=switch (dataElement) {
			case StructuredDataType d -> output+=ttcnName(e.getDataElement())+":{"+assignedArguments+"}";
			case StructuredDataType d -> output+="{"+assignedArguments+"}";
			case StructuredDataInstance d -> output+=ttcnName(e.getDataElement());
			case Function d -> output+=ttcnName(e.getDataElement())+"("+arguments+")";
			case Parameter d -> output+=ttcnName(e.getDataElement());
@@ -256,6 +290,44 @@ public class TTCN3Renderer {
			default -> "NOT_SUPPORTED_YET";
			};
		}
		output+=renderReduction(e, indent);
		return output;
	}

	String render(Parameter p, DataUse e, String indent) {
		String output = "";
		//TODO: check that it conforms?
		//TODO: add to spec?
		String direct = render(e, "");
		if (p.getDataType() instanceof StructuredDataType) {
			if (e.resolveDataType() == p.getDataType()) {
				output+=direct;
			} else {
				output+="{ extensions := { "+ttcnName(e.resolveDataType())+" := "+render(e, "")+"}}";
			}
		} else {
			output+=direct;
		}
		return output;
	}

	String render(CastDataUse e, String indent) {
		//TODO: add to spec?
		String output = "";
		output+=render(e.getDataUse(), "");
		//skip superfluous casts
		if (e.getDataType() != e.getDataUse().resolveDataType()) {
			output+=".extensions."+ttcnName(e.getDataType());
		}
		output+=renderReduction(e, indent);
		return output;
	}

	String renderReduction(DataUse e, String indent) {
		String output = "";
		if (!e.getReduction().isEmpty()) {
			output+="."+e.getReduction().stream().map(m -> ttcnName(m.getMember())).collect(Collectors.joining("."));
		}
		return output;
	}