Skip to content

Commit

Permalink
Add witness to string capability
Browse files Browse the repository at this point in the history
  • Loading branch information
rdhananjaya committed Jul 11, 2022
1 parent 08bdecb commit aa965a2
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 24 deletions.
5 changes: 2 additions & 3 deletions compiler/modules/bir/bir.bal
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import wso2/nballerina.types as t;
import wso2/nballerina.comm.err;
import wso2/nballerina.comm.diagnostic as d;
import wso2/nballerina.front.'type.witness as w;

public type SemType t:SemType;
public type Position d:Position;
Expand Down Expand Up @@ -384,9 +383,9 @@ public type BooleanOperand BooleanConstOperand|Register;
public type StringOperand StringConstOperand|Register;
public type FunctionOperand FunctionRef|Register;

public function operandHasType(t:Context tc, Operand operand, t:SemType semType) returns [boolean, string] {
public function operandHasType(t:Context tc, Operand operand, t:SemType semType) returns boolean {
t:WitnessCollector witness = new(tc);
return [t:isSubtypeWitness(tc, operand.semType, semType, witness), w:typeWitnessToString(witness)];
return t:isSubtypeWitness(tc, operand.semType, semType, witness);
}

# Perform a arithmetic operand on ints with two operands.
Expand Down
2 changes: 1 addition & 1 deletion compiler/modules/bir/verify.bal
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class VerifyContext {
}

function operandHasType(Operand operand, t:SemType t) returns boolean {
return operandHasType(self.tc, operand, t)[0];
return operandHasType(self.tc, operand, t);
}

function isSameType(t:SemType t1, t:SemType t2) returns boolean {
Expand Down
82 changes: 82 additions & 0 deletions compiler/modules/front.syntax/witnessExpr.bal
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import wso2/nballerina.types as t;

public function typeWitnessToString(t:WitnessCollector witness) returns string {
t:WitnessValue value = witness.get();
if value is string {
return value;
}
else if value == () {
return "";
}
else {
Expr expr = nonStringWitnessToExpr(value);
return exprToString(expr);
}
}

public function typeWitnessToExpr(t:WitnessValue value) returns Expr {
if value == () || value is string {
return { startPos: 0, endPos: 0, value };
}
else {
return nonStringWitnessToExpr(value);
}
}

function nonStringWitnessToExpr(t:WrappedSingleValue|map<t:WitnessValue>|t:ListWitnessValue value) returns Expr {
if value is t:WrappedSingleValue {
return singleValueToLiteral(value);
}
else if value is map<t:WitnessValue> {
return mappingWitnessToLiteral(value);
}
else if value is t:ListWitnessValue {
return listWitnessToLiteral(value);
}
}

function listWitnessToLiteral(t:ListWitnessValue value) returns ListConstructorExpr {
var { memberValues, indices, fixedLen } = value;
Expr[] members = [];
foreach int i in 0 ..< memberValues.length() {
Expr m = typeWitnessToExpr(memberValues[i]);
if i + 1 < indices.length() {
int nextIndex = indices[i + 1];
members.push(m);
foreach var _ in members.length() ..< nextIndex {
members.push(m);
}
}
}

foreach int i in members.length() ..< fixedLen {
members.push(typeWitnessToExpr(memberValues[memberValues.length() - 1]));
}
return { startPos: 0, endPos: 0, opPos: 0, members };
}

function mappingWitnessToLiteral(map<t:WitnessValue> value) returns MappingConstructorExpr {
int startPos = 0;
int endPos = 0;
Field[] fields = from var [name, val] in value.entries()
select { startPos, endPos, colonPos: startPos, isIdentifier: true, name, value: typeWitnessToExpr(val) };
return { startPos, endPos, opPos: startPos, fields };
}

function singleValueToLiteral(t:WrappedSingleValue value) returns LiteralExpr|NumericLiteralExpr {
t:SingleValue v = value.value;
int startPos = 0;
int endPos = 0;
if v == () || v is string || v is boolean {
return { startPos, endPos, value: v };
}
else if v is int {
return { startPos, endPos, base: 10, digits: v.toString() };
}
else if v is float {
return { startPos, endPos, typeSuffix: "f", untypedLiteral: v.toString() };
}
else if v is decimal {
return { startPos, endPos, typeSuffix: "d", untypedLiteral: v.toString() };
}
}
7 changes: 0 additions & 7 deletions compiler/modules/front.type.witness/witnessExpr.bal

This file was deleted.

8 changes: 7 additions & 1 deletion compiler/modules/types/list.bal
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ public type FixedLengthArray record {|
// The SemTypes in this list are not `never`.
public type ListMemberTypes [Range[], SemType[]];

public type ListSubtypeWitness readonly & record {|
SemType[] memberTypes;
int[] indices;
int fixedLen;
|};

public function listAtomicTypeMemberAt(ListAtomicType atomic, int i) returns SemType {
if i < atomic.members.fixedLength {
int initialLen = atomic.members.initial.length();
Expand Down Expand Up @@ -273,7 +279,7 @@ function listIntersectWith(FixedLengthArray members1, SemType rest1, FixedLength
// `neg` represents N.
function listInhabited(Context cx, int[] indices, SemType[] memberTypes, int nRequired, Conjunction? neg, int fixedLen, WitnessCollector witness) returns boolean {
if neg == () {
witness.remainingListType({ fixedLen, indices: indices.cloneReadOnly(), memberTypes: memberTypes.cloneReadOnly() });
witness.remainingSubType({ fixedLen, indices: indices.cloneReadOnly(), memberTypes: memberTypes.cloneReadOnly() });
return true;
}
else {
Expand Down
23 changes: 13 additions & 10 deletions compiler/modules/types/witness.bal
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import wso2/nballerina.comm.lib;

public type WitnessableSubtype MappingAtomicType|StringSubtype|DecimalSubtype|FloatSubtype|IntSubtype|BooleanSubtype;
public type WitnessableSubtype MappingAtomicType|ListSubtypeWitness|StringSubtype|DecimalSubtype|FloatSubtype|IntSubtype|BooleanSubtype;

public type ListWitness readonly & record {|
SemType[] memberTypes;
public type ListWitnessValue readonly & record {|
WitnessValue[] memberValues;
int[] indices;
int fixedLen;
|};

public type WitnessValue WrappedSingleValue|string|map<WitnessValue>|ListWitness?;
public type WitnessValue WrappedSingleValue|string|map<WitnessValue>|ListWitnessValue?;

final readonly & [UniformTypeBitSet, WrappedSingleValue|string][] uniformTypeSample = [
[NEVER, "never"],
Expand Down Expand Up @@ -46,12 +46,6 @@ public class WitnessCollector {
}
}

public function remainingListType(ListWitness listWitness) {
if self.witness == () {
self.witness = listWitness;
}
}

public function allOfTypes(UniformTypeBitSet all) {
self.witness = uniformTypesToWitnessValue(all);
}
Expand Down Expand Up @@ -111,6 +105,9 @@ function subtypeToWitnessValue(Context cx, WitnessableSubtype subtype) returns W
else if subtype is BooleanSubtype {
return createBooleanWitness(subtype);
}
else if subtype is ListSubtypeWitness {
return createListWitness(cx, subtype);
}
else {
return createIntWitness(subtype);
}
Expand Down Expand Up @@ -138,6 +135,12 @@ function createMappingWitness(Context cx, MappingAtomicType subtype) returns Wit
return witness;
}

function createListWitness(Context cx, ListSubtypeWitness listWitnessType) returns ListWitnessValue {
var { memberTypes, indices, fixedLen } = listWitnessType;
WitnessValue[] memberValues = from var m in memberTypes select semTypeToWitnessValue(cx, m);
return { memberValues: memberValues.cloneReadOnly(), indices, fixedLen };
}

function createStringWitness(StringSubtype subtype) returns WrappedSingleValue {
var { char, nonChar } = subtype;
if nonChar.allowed {
Expand Down
3 changes: 1 addition & 2 deletions compiler/tests/testSuite.bal
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import wso2/nballerina.front;
import ballerina/io;
import wso2/nballerina.types as t;
import wso2/nballerina.front.syntax as s;
import wso2/nballerina.front.'type.witness as w;

import wso2/nballerina.comm.err;
import wso2/nballerina.comm.diagnostic as d;
Expand Down Expand Up @@ -243,7 +242,7 @@ function testSemtypeWitness(front:SourcePart[] sources, string[] expected) retur

t:WitnessCollector w = new(tc);
boolean lsr = t:isSubtypeWitness(tc, left, right, w);
string witness = w:typeWitnessToString(w);
string witness = s:typeWitnessToString(w);
match test.op {
"<" => {
test:assertEquals(lsr, false, string `${lhsStr} is not a proper subtype of ${rhsStr}`);
Expand Down

0 comments on commit aa965a2

Please sign in to comment.