Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generated code for functions to all follow same structure #43

Closed
jim-h-wang opened this issue Sep 11, 2019 · 6 comments
Closed

Generated code for functions to all follow same structure #43

jim-h-wang opened this issue Sep 11, 2019 · 6 comments
Assignees
Labels
high-priority High priority issues

Comments

@jim-h-wang
Copy link
Contributor

func RateOfReturn utilises code generators that were used for (the now deprecated) calculations. We should aim to have a consistent structure and api for all generated code that relate to Rosetta Functions.

Additionally, This causes incompatibility in the java code when new-style functions reference old-style functions. In the below example, func EquityReset was modified to call func RateOfReturn, which yielded the below error in the generated code for EquityReset.

image

@jim-h-wang
Copy link
Contributor Author

Reopening this issue as the structure and API of the generated java code for Functions is not consistent.

Generated java code for EquityResetEvent follows the new structure:

/**
 * Function specification for resetting an equity payout following an equity price observation, which means calculating the equity performance and resetting the equity notional.
 */
@ImplementedBy(EquityResetEventImpl.class)
public abstract class EquityResetEvent implements RosettaFunction {
	
	// RosettaFunction dependencies
	//
	@Inject protected EquityReset equityReset;
		
	/**
	 * @param contract 
	 * @param observation 
	 * @return reset 
	 */
	public Event evaluate(Contract contract, Event observation) {
		// pre-conditions
		//
		assert
			exists(MapperS.of(contract).<ContractualProduct>map("getContractualProduct", Contract::getContractualProduct).<EconomicTerms>map("getEconomicTerms", ContractualProduct::getEconomicTerms).<Payout>map("getPayout", EconomicTerms::getPayout).<EquityPayout>mapC("getEquityPayout", Payout::getEquityPayout), false).get() &&
			exists(MapperS.of(observation).<PrimitiveEvent>map("getPrimitive", Event::getPrimitive).<ObservationPrimitive>mapC("getObservation", PrimitiveEvent::getObservation), false).get()
				: "There must be an equity payout on the contract, and the event input must contain an observation.";
		assert
			areEqual(MapperS.of(observation).<PrimitiveEvent>map("getPrimitive", Event::getPrimitive).<ObservationPrimitive>mapC("getObservation", PrimitiveEvent::getObservation).<BigDecimal>map("getObservation", ObservationPrimitive::getObservation), MapperS.of(BigDecimal.valueOf(3.0))).get()
				: "";
		// Delegate to implementation
		//
		Event reset = doEvaluate(contract, observation);
		// post-conditions
		//
		assert
			areEqual(MapperS.of(reset).<PrimitiveEvent>map("getPrimitive", Event::getPrimitive).<ResetPrimitive>mapC("getReset", PrimitiveEvent::getReset), MapperS.of(equityReset.calculate(MapperS.of(contract).<ContractualProduct>map("getContractualProduct", Contract::getContractualProduct).<EconomicTerms>map("getEconomicTerms", ContractualProduct::getEconomicTerms).<Payout>map("getPayout", EconomicTerms::getPayout).<EquityPayout>mapC("getEquityPayout", Payout::getEquityPayout).get(), MapperS.of(observation).<PrimitiveEvent>map("getPrimitive", Event::getPrimitive).<ObservationPrimitive>mapC("getObservation", PrimitiveEvent::getObservation).<BigDecimal>map("getObservation", ObservationPrimitive::getObservation).get(), MapperS.of(observation).<PrimitiveEvent>map("getPrimitive", Event::getPrimitive).<ObservationPrimitive>mapC("getObservation", PrimitiveEvent::getObservation).<Date>map("getDate", ObservationPrimitive::getDate).get()))).get() &&
			exists(MapperS.of(reset).<PrimitiveEvent>map("getPrimitive", Event::getPrimitive).<ResetPrimitive>mapC("getReset", PrimitiveEvent::getReset), true).get()
				: "Event must contain a reset primitive that is calculated based on the observation, and no other primitive.";
		assert
			areEqual(MapperS.of(reset).<EventEffect>map("getEventEffect", Event::getEventEffect).mapC("getEffectedContract", EventEffect::getEffectedContract).<Contract>map("getValue", FieldWithMeta::getValue), MapperS.of(contract)).get() &&
			areEqual(MapperS.of(reset).<EventEffect>map("getEventEffect", Event::getEventEffect).mapC("getContract", EventEffect::getContract).<Contract>map("getValue", FieldWithMeta::getValue), MapperS.of(contract)).get() &&
			notExists(MapperS.of(reset).<EventEffect>map("getEventEffect", Event::getEventEffect).mapC("getEffectedExecution", EventEffect::getEffectedExecution).<Execution>map("getValue", FieldWithMeta::getValue)).get() &&
			notExists(MapperS.of(reset).<EventEffect>map("getEventEffect", Event::getEventEffect).mapC("getExecution", EventEffect::getExecution).<Execution>map("getValue", FieldWithMeta::getValue)).get() &&
			notExists(MapperS.of(reset).<EventEffect>map("getEventEffect", Event::getEventEffect).mapC("getProductIdentifier", EventEffect::getProductIdentifier).<ProductIdentifier>map("getValue", FieldWithMeta::getValue)).get()
				: "Event effect must include the notional reset on the contract.";
		assert
			areEqual(MapperS.of(reset).<Lineage>map("getLineage", Event::getLineage).mapC("getContractReference", Lineage::getContractReference).<Contract>map("getValue", FieldWithMeta::getValue), MapperS.of(contract)).get() &&
			areEqual(MapperS.of(reset).<Lineage>map("getLineage", Event::getLineage).mapC("getEventReference", Lineage::getEventReference).<Event>map("getValue", FieldWithMeta::getValue), MapperS.of(observation)).get()
				: "Event lineage must point to the contract being reset and the observation event.";
		return reset;
	}
		
	protected abstract Event doEvaluate(Contract contract, Event observation);
}

Generated code for EquityReset still on old structure

public class EquityReset {
	
	private final GetBusinessDateSpec getBusinessDateSpec;
	private final EquityCalculationPeriod equityCalculationPeriod;
	private final ResolvePrice resolvePrice;
	private final RateOfReturn rateOfReturn;
	private final EquityNotionalAmount equityNotionalAmount;
	private final EquityPerformance equityPerformance;
	private final Abs abs;
	private final EquityCashSettlementAmount equityCashSettlementAmount;
	
	public EquityReset(GetBusinessDateSpec getBusinessDateSpec, EquityCalculationPeriod equityCalculationPeriod, ResolvePrice resolvePrice, RateOfReturn rateOfReturn, EquityNotionalAmount equityNotionalAmount, EquityPerformance equityPerformance, Abs abs, EquityCashSettlementAmount equityCashSettlementAmount) {
		this.getBusinessDateSpec = getBusinessDateSpec;
		this.equityCalculationPeriod = equityCalculationPeriod;
		this.resolvePrice = resolvePrice;
		this.rateOfReturn = rateOfReturn;
		this.equityNotionalAmount = equityNotionalAmount;
		this.equityPerformance = equityPerformance;
		this.abs = abs;
		this.equityCashSettlementAmount = equityCashSettlementAmount;
	}
	
	public CalculationResult calculate(EquityPayout equityPayout, BigDecimal observation, Date date) {
		CalculationInput input = new CalculationInput().create(equityPayout, observation, date, getBusinessDateSpec, equityCalculationPeriod, resolvePrice, rateOfReturn, equityNotionalAmount, equityPerformance, abs, equityCashSettlementAmount);
		CalculationResult result = new CalculationResult(input);
		if(result.reset == null) result.reset = ResetPrimitive.builder().build();
		ResetPrimitive.ResetPrimitiveBuilder __builder = result.reset.toBuilder();
		__builder.getOrCreateAfter().getOrCreateUpdatedContract().getOrCreateContractualProduct().getOrCreateEconomicTerms().getOrCreatePayout().getOrCreateEquityPayout(0).setRateOfReturn(rateOfReturn.calculate(equityPayout).getRateOfReturn());
		result.reset = __builder.build();
		__builder.getOrCreateAfter().getOrCreateUpdatedContract().getOrCreateContractualProduct().getOrCreateEconomicTerms().getOrCreatePayout().getOrCreateEquityPayout(0).setPerformance(equityPerformance.calculate(equityPayout).getEquityPerformance());
		result.reset = __builder.build();
		__builder.getOrCreateAfter().getOrCreateUpdatedContract().getOrCreateContractualProduct().getOrCreateEconomicTerms().getOrCreatePayout().getOrCreateEquityPayout(0).setEquityCashSettlementAmount(equityCashSettlementAmount.calculate(equityPayout).getEquityCashSettlementAmount());
		result.reset = __builder.build();
		__builder.getOrCreateBefore().getOrCreateUpdatedContract().getOrCreateContractualProduct().getOrCreateEconomicTerms().getOrCreatePayout().addEquityPayout(equityPayout);
		result.reset = __builder.build();
		return result;
	}
	public static class CalculationInput implements ICalculationInput {
		private CalculationInput input = this;  // For when arguments need to reference other arguments
		private EquityPayout equityPayout;
		private BigDecimal observation;
		private Date date;
		
		public CalculationInput create(EquityPayout equityPayout, BigDecimal observation, Date date, GetBusinessDateSpec getBusinessDateSpec, EquityCalculationPeriod equityCalculationPeriod, ResolvePrice resolvePrice, RateOfReturn rateOfReturn, EquityNotionalAmount equityNotionalAmount, EquityPerformance equityPerformance, Abs abs, EquityCashSettlementAmount equityCashSettlementAmount) {
			this.equityPayout = equityPayout;
			this.observation = observation;
			this.date = date;
			return this;
		}
	
		@Override
		public List<Formula> getFormulas() {
			return Arrays.asList(
			new Formula("EquityReset", "RateOfReturn( equityPayout )", this),
			new Formula("EquityReset", "EquityPerformance( equityPayout )", this),
			new Formula("EquityReset", "EquityCashSettlementAmount( equityPayout )", this),
			new Formula("EquityReset", "equityPayout", this));
		}
		
		public EquityPayout getEquityPayout() {
			return equityPayout;
		}
	
		public BigDecimal getObservation() {
			return observation;
		}
	
		public Date getDate() {
			return date;
		}
	
		private static final List<Attribute<?>> ATTRIBUTES =  Arrays.asList(
		);
	
		@Override
		public List<Attribute<?>> getAttributes() {
			return ATTRIBUTES;
		}
		
	}
	
	public static class CalculationResult implements ICalculationResult {
	
		private CalculationInput calculationInput;
	
		private ResetPrimitive reset;
		
		public CalculationResult(CalculationInput calculationInput) {
			this.calculationInput = calculationInput;
		}
		public ResetPrimitive getReset() {
			return this.reset;
		}
		
		public CalculationResult setReset(ResetPrimitive reset) {
			this.reset = reset;
			return this;
		}
		
		@Override
		public CalculationInput getCalculationInput() {
			return calculationInput;
		}
		
		private static final List<Attribute<?>> ATTRIBUTES =  Arrays.asList(
			new Attribute<>("reset", ResetPrimitive.class, (IResult res) -> ((CalculationResult) res).getReset())
		);
	
		@Override
		public List<Attribute<?>> getAttributes() {
			return ATTRIBUTES;
		}
		
		@Override
		public boolean equals(Object o) {
			if (this == o) return true;
			if (o == null || getClass() != o.getClass()) return false;
		
			CalculationResult _that = (CalculationResult) o;
		
			if (reset != null ? !reset.equals(_that.reset) : _that.reset != null) return false;
			return true;
		}
		
		@Override
		public int hashCode() {
			int _result = 0;
			_result = 31 * _result + (reset != null ? reset.hashCode() : 0);
			return _result;
		}
		
		@Override
		public String toString() {
			return "CalculationResult {" +
				"reset=" + this.reset +
			'}';
		}
	}
}

Desired generated code structure for EquityReset:

/**
 * Function specification for resetting an equity payout following an equity price observation. This function only concerns itself with building the primitive, which currently does not affect the underlying contract (until such time when 'ResetPrimitive' is refactored to directly accomodate a 'before' and 'after' states). The contract effect will be part of the 'EventEffect' attribute on the a fully-formed Business Event that is built by the 'EquityResetEvent' function spec.
 */
@ImplementedBy(EquityResetNewImpl.class)
public abstract class EquityReset implements RosettaFunction {
	
	// RosettaFunction dependencies
	//
	@Inject protected CalculationPeriod calculationPeriod;
	@Inject protected RateOfReturn rateOfReturn;
	@Inject protected EquityPerformance equityPerformance;
	@Inject protected EquityCashSettlementAmount equityCashSettlementAmount;
		
	/**
	 * @param equityPayout 
	 * @param number 
	 * @return date 
	 */
	public ResetPrimitive evaluate(EquityPayout equityPayout, BigDecimal number, Date date) {
		// pre-conditions
		//
		assert
			areEqual(MapperS.of(date), MapperS.of(calculationPeriod.evaluate(MapperS.of(equityPayout).<CalculationPeriodDates>map("getCalculationPeriodDates", EquityPayout::getCalculationPeriodDates).get()).getEndDate())).get()
				: "The reset date must be the period end date on the equity payout.";

		// Delegate to implementation
		//
		ResetPrimitiveBuilder resetBuilder = doEvaluate(equityPayout, number, date);

		// Assign values to the output
		//
		resetBuilder.getOrCreateAfter().getOrCreateUpdatedContract().getOrCreateContractualProduct().getOrCreateEconomicTerms().getOrCreatePayout().getOrCreateEquityPayout(0).setRateOfReturn(rateOfReturn.calculate(equityPayout).getRateOfReturn());
		resetBuilder.getOrCreateAfter().getOrCreateUpdatedContract().getOrCreateContractualProduct().getOrCreateEconomicTerms().getOrCreatePayout().getOrCreateEquityPayout(0).setPerformance(equityPerformance.calculate(equityPayout).getEquityPerformance());
		resetBuilder.getOrCreateAfter().getOrCreateUpdatedContract().getOrCreateContractualProduct().getOrCreateEconomicTerms().getOrCreatePayout().getOrCreateEquityPayout(0).setEquityCashSettlementAmount(equityCashSettlementAmount.calculate(equityPayout).getEquityCashSettlementAmount());
		resetBuilder.getOrCreateBefore().getOrCreateUpdatedContract().getOrCreateContractualProduct().getOrCreateEconomicTerms().getOrCreatePayout().addEquityPayout(equityPayout);
		
		ResetPrimitive reset = resetBuilder.build();
		
		return reset;
	}
		
	protected abstract ResetPrimitiveBuilder doEvaluate(EquityPayout equityPayout, BigDecimal number, Date date);
}

There will be a number of downstream clients that will require updating.

@dhuebner
Copy link
Contributor

dhuebner commented Sep 12, 2019

@jim-h-wang Should we also remove calculation spec and function (except library) from the grammar ?

@dhuebner
Copy link
Contributor

@jim-h-wang And don't forget the daycountfraction enum function.

@jim-h-wang
Copy link
Contributor Author

@jim-h-wang Should we also remove calculation spec and function (except library) from the grammar ?

Yes we should

@jim-h-wang
Copy link
Contributor Author

jim-h-wang commented Sep 13, 2019

@dhuebner

A model example of a function that makes use of alias' on inputs and outputs, conditions, post-conditions and has multiple assignments

func EquityReset: <"Function specification for resetting an equity payout following an equity price observation. This function only concerns itself with building the primitive, which currently does not affect the underlying contract (until such time when 'ResetPrimitive' is refactored to directly accomodate a 'before' and 'after' states). The contract effect will be part of the 'EventEffect' attribute on the a fully-formed Business Event that is built by the 'EquityResetEvent' function spec.">
	inputs:
		equityPayout EquityPayout (1..1)
		// source ObservationSource (1..1)
		observation number (1..1)
		date date (1..1)		
	
	output:
		reset ResetPrimitive (1..1)
	
	alias effectiveDate :
		equityPayout -> calculationPeriodDates -> effectiveDate -> adjustableDate -> adjustedDate
		
	alias stepSchedule :
		equityPayout -> payoutQuantity -> quantitySchedule -> stepSchedule
		
	alias scheduleDates :
		stepSchedule -> step -> stepDate
	
	// alias on the output
	alias EquityPayout_after: <"TODO: should be usable in assign-output blocks.">
		reset -> after -> updatedContract -> contractualProduct -> economicTerms -> payout -> equityPayout only-element
		
	alias EquityPayout_before: <"TODO: should be usable in assign-output blocks.">
		reset -> before -> updatedContract -> contractualProduct -> economicTerms -> payout -> equityPayout only-element
		
	condition date_is_period_end_date : 
		<"The reset date must be the period end date on the equity payout.">
		date = CalculationPeriod( equityPayout -> calculationPeriodDates ) -> endDate;
		
	condition : <"effective date should be in the past.">
		if effectiveDate exists then effectiveDate < date;
		
	condition : <"A step schedule needs to have more than 1 date.">
		if stepSchedule exists then scheduleDates count > 1;
		
	// TODO: use alias EquityPayout_before when feature is available
	assign-output reset -> before -> updatedContract -> contractualProduct -> economicTerms -> payout -> equityPayout : 
		<"Reset primitive before state must be correctly populated with the equity payout that is being reset.">
		equityPayout
	
	// TODO: use alias EquityPayout_after when feature is available	
	assign-output reset -> after -> updatedContract -> contractualProduct -> economicTerms -> payout -> equityPayout -> rateOfReturn : 
		<"Reset primitive after state must be correctly populated with the equity payout including the rate of return.">
		RateOfReturn( equityPayout )
		
	// TODO: use alias EquityPayout_after when feature is available		
	assign-output reset -> after -> updatedContract -> contractualProduct -> economicTerms -> payout -> equityPayout -> performance : 
		<"Reset primitive after state must be correctly populated with the equity payout including the performance.">
		EquityPerformance( equityPayout )
		
	// TODO: use alias EquityPayout_after when feature is available	
	assign-output reset -> after -> updatedContract -> contractualProduct -> economicTerms -> payout -> equityPayout -> equityCashSettlementAmount : 
		<"Reset primitive after state must be correctly populated with the equity payout including the cash settlement amount.">
		EquityCashSettlementAmount( equityPayout )
		
	post-condition : <"updatedContract values between before and after should be different.">
		reset -> after -> updatedContract <> reset -> before -> updatedContract;

And what I think should get generated (which is yet untested).

A point to note is that for generated code will be different between alias on inputs vs alias on the output.

/**
 * Function specification for resetting an equity payout following an equity price observation. This function only concerns itself with building the primitive, which currently does not affect the underlying contract (until such time when 'ResetPrimitive' is refactored to directly accomodate a 'before' and 'after' states). The contract effect will be part of the 'EventEffect' attribute on the a fully-formed Business Event that is built by the 'EquityResetEvent' function spec.
 */
//@ImplementedBy(EquityResetNewImpl.class)
public abstract class EquityResetNew implements RosettaFunction {
	
	// RosettaFunction dependencies
	//
	@Inject protected CalculationPeriod calculationPeriod;
	@Inject protected RateOfReturn rateOfReturn;
	@Inject protected EquityPerformance equityPerformance;
	@Inject protected EquityCashSettlementAmount equityCashSettlementAmount;
			
	/**
	 * @param equityPayout 
	 * @param number 
	 * @return date
	 */
	public ResetPrimitive evaluate(EquityPayout equityPayout, BigDecimal number, Date date) {
		
		// Define alias on inputs
		//
		MapperBuilder<Date> aliasEffectiveDate = aliasEffectiveDate(equityPayout);
		
		MapperBuilder<NonNegativeStepSchedule> aliasStepSchedule = aliasStepSchedules(equityPayout);
		
		MapperBuilder<Date> aliasScheduleDates = aliasScheduleDates(equityPayout);
		
		
		// pre-conditions
		//
		assert
			areEqual(MapperS.of(date), MapperS.of(calculationPeriod.evaluate(MapperS.of(equityPayout).<CalculationPeriodDates>map("getCalculationPeriodDates", EquityPayout::getCalculationPeriodDates).get()).getEndDate())).get()
				: "The reset date must be the period end date on the equity payout.";
			
		assert 
			doIf(exists(aliasEffectiveDate, false), lessThan(aliasEffectiveDate, MapperS.of(date)), MapperS.of(Boolean.TRUE)).get()
				: "effective date should be in the past.";
			
		assert
			doIf(exists(aliasStepSchedule, false), greaterThan(MapperS.of(aliasScheduleDates.resultCount()), MapperS.of(1)), MapperS.of(Boolean.TRUE)).get()
				: "A step schedule needs to have more than 1 date.";
			
			
		// Delegate to implementation
		//
		ResetPrimitiveBuilder resetPrimitiveBuilder = doEvaluate(equityPayout, number, date);

		
		// Assign values to the output
		//
		aliasEquityPayoutAfter(resetPrimitiveBuilder)
			.setRateOfReturn(rateOfReturn.calculate(equityPayout).getRateOfReturn());
		
		aliasEquityPayoutAfter(resetPrimitiveBuilder)
			.setPerformance(equityPerformance.calculate(equityPayout).getEquityPerformance());
		
		aliasEquityPayoutAfter(resetPrimitiveBuilder)
			.setEquityCashSettlementAmount(equityCashSettlementAmount.calculate(equityPayout).getEquityCashSettlementAmount());
		
		aliasPayoutBefore(resetPrimitiveBuilder)
			.addEquityPayout(equityPayout);
		
		
			
		// post-conditions
		//
		assert
			notEqual(MapperS.of(resetPrimitiveBuilder).<ContractStateBuilder>map("getAfter", ResetPrimitiveBuilder::getAfter).<ContractBuilder>map("getUpdatedContract", ContractStateBuilder::getUpdatedContract), MapperS.of(resetPrimitiveBuilder).<ContractStateBuilder>map("getBefore", ResetPrimitiveBuilder::getBefore).<ContractBuilder>map("getUpdatedContract", ContractStateBuilder::getUpdatedContract)).get()
				: "updatedContract values between before and after should be different.";
		
		// Build and return the output object
		//
		return resetPrimitiveBuilder.build();
	}
		
	protected abstract ResetPrimitiveBuilder doEvaluate(EquityPayout equityPayout, BigDecimal number, Date date);
	
	private EquityPayoutBuilder aliasEquityPayoutAfter(ResetPrimitiveBuilder resetPrimitive) {
		return resetPrimitive.getOrCreateAfter().getOrCreateUpdatedContract().getOrCreateContractualProduct().getOrCreateEconomicTerms().getOrCreatePayout().getOrCreateEquityPayout(0);
	}
	
	private PayoutBuilder aliasPayoutBefore(ResetPrimitiveBuilder resetPrimitive) {
		return resetPrimitive.getOrCreateBefore().getOrCreateUpdatedContract().getOrCreateContractualProduct().getOrCreateEconomicTerms().getOrCreatePayout();
	}
	
	private MapperBuilder<Date> aliasEffectiveDate(EquityPayout equityPayout) {
		return MapperS.of(equityPayout)
				.<CalculationPeriodDates>map("getCalculationPeriodDates", EquityPayout::getCalculationPeriodDates)
				.<AdjustableOrRelativeDate>map("getAdjustableOrRelativeDate", CalculationPeriodDates::getEffectiveDate)
				.<AdjustableDate>map("getAdjustableDate", AdjustableOrRelativeDate::getAdjustableDate)
				.<FieldWithMetaDate>map("getAdjustedDate", AdjustableDate::getAdjustedDate)
				.<Date>map("getValue", FieldWithMetaDate::getValue);
	}
	
	private MapperBuilder<NonNegativeStepSchedule> aliasStepSchedules(EquityPayout equityPayout) {
		return MapperS.of(equityPayout)
				.<ResolvablePayoutQuantity>map("getPayoutQuantity", EquityPayout::getPayoutQuantity)
				.<NonNegativeQuantitySchedule>map("getQuantitySchedule", ResolvablePayoutQuantity::getQuantitySchedule)
				.<NonNegativeStepSchedule>map("getStepSchedule", NonNegativeQuantitySchedule::getStepSchedule);
	}
	
	private MapperBuilder<Date> aliasScheduleDates(EquityPayout equityPayout) {
		return aliasStepSchedules(equityPayout)
				.<NonNegativeStep>mapC("getStep", NonNegativeStepSchedule::getStep)
				.<Date>map("getDate", NonNegativeStep::getStepDate);
	}
}

dhuebner added a commit that referenced this issue Sep 16, 2019
dhuebner added a commit that referenced this issue Sep 17, 2019
dhuebner added a commit that referenced this issue Sep 17, 2019
dhuebner added a commit that referenced this issue Sep 18, 2019
dhuebner added a commit that referenced this issue Sep 20, 2019
@dhuebner dhuebner added needs review Needs review from a core developer and removed in progress labels Sep 23, 2019
jim-h-wang pushed a commit that referenced this issue Sep 23, 2019
* Allow alias in assignment #43
* Move calculation impl to the doEvaluate method #43
* Additiona FuncGenerator fixes. Adjusted test expectation #43
* Added type check for assign-output
* Added Reference type support #43
* Allow usage of output in assign expression #43
* Added cardinality and name validation. Better type inference for if-else
* Allow only-element for callable call
* assignment of an alias #53
* Validate list element access #65
@dhuebner dhuebner removed the needs review Needs review from a core developer label Sep 23, 2019
@dhuebner
Copy link
Contributor

merged

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
high-priority High priority issues
Projects
None yet
Development

No branches or pull requests

2 participants