Skip to content

Commit

Permalink
Move Array to a non-custom type
Browse files Browse the repository at this point in the history
  • Loading branch information
maxsklar committed Oct 6, 2023
1 parent d7d0888 commit d6dbecd
Show file tree
Hide file tree
Showing 12 changed files with 139 additions and 59 deletions.
5 changes: 0 additions & 5 deletions src/main/newmap/system/init.nm
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,11 @@ update _default: (Count:0)
update _default: (Boolean:0)
update _default: (Type: UndefinedType)

// TODO - include this!
//update _default ((Array:T):(0: ()))

data String = Array|Char

typeclass _display (t: (t => String))
update _display: (String: (s: s))

//case CustomT("Array", nType) => Success(UCase(UIndex(0), UArray()))

//data Option (T: Type)
//update Option: (None, ())
//update Option: (Some, T)
Expand Down
14 changes: 5 additions & 9 deletions src/main/scala/ai/newmap/interpreter/IterationUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,10 @@ object IterationUtils {
case NewMapObject(UArray(_), MapT(typeTransform, MapConfig(RequireCompleteness, BasicMap, _, _, _))) => {
enumerateAllValuesIfPossible(typeTransform.keyType, env)
}
case NewMapObject(UCase(UIndex(_), UArray(values)), CustomT("Array", _, _)) => {
Success(values.toVector)
}
case NewMapObject(UCase(UIndex(_), UMap(values)), CustomT("Array", _, _)) => {
// We should be more careful about the ordering here!!
Success(values.map(_._2))
case NewMapObject(UCase(UIndex(_), values), ArrayT(_)) => {
for {
mapBindings <- values.getMapBindings()
} yield mapBindings.map(_._2)
}
case NewMapObject(untaggedCurrent, CustomT(typeName, params, typeSystemId)) => {
for {
Expand Down Expand Up @@ -167,9 +165,7 @@ object IterationUtils {
case MapT(typeTransform, MapConfig(RequireCompleteness, BasicMap, _, _, _)) => {
Success(typeTransform.valueType)
}
case CustomT("Array", itemType, _) => {
itemType.asType
}
case ArrayT(itemT) => Success(itemT)
case CustomT(typeName, params, typeSystemId) => {
for {
// TODO - use TypeChecker.getUnderlyingType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ object PatternCoverageCalculator {
case _ => false
}
}
case UCase(UWildcard(_), UWildcard(_)) => true
case _ => false
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ object StatementInterpreter {

nTypeObj <- Evaluator(tcType.nExpression, env)

//_ = println("got tc type obj: " + nTypeObj)

nType <- nTypeObj.asType

//_ = println("Expected type: " + nType.displayString(env))
Expand Down Expand Up @@ -59,8 +57,6 @@ object StatementInterpreter {
nTypeObj <- Evaluator(tcType.nExpression, env)
nType <- nTypeObj.asType

// Problem is WITH_TYPE!!

// TODO: Maybe a special error message if this is not a command type
// - In fact, we have yet to build an actual command type checker
_ <- UpdateCommandCalculator.getDefaultValueOfCommandType(nType, env)
Expand Down
81 changes: 71 additions & 10 deletions src/main/scala/ai/newmap/interpreter/TypeChecker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -266,15 +266,6 @@ object TypeChecker {
TypeCheckResponse(UMap(result), expectedType)
}
}
case Success(MapT(typeTransform, MapConfig(MapPattern, internalFeatureSet, _, _, _))) => {
for {
_ <- Outcome.failWhen(values.length > 1, "Map Pattern can only have 1 key-value pair: " + values)
value <- Outcome(values.headOption, "Empty Map Pattern")
mapValue <- typeCheckGenericMap(Vector(value), typeTransform, internalFeatureSet, env, featureSet, tcParameters)
} yield {
TypeCheckResponse(UMap(mapValue), expectedType)
}
}
case Success(MapT(typeTransform, config)) => {
val isArrayInput = llType == ArrayType
val correctedValues = if (isArrayInput) {
Expand Down Expand Up @@ -409,6 +400,25 @@ object TypeChecker {
TypeCheckResponse(UCase(firstObj, secondExp.nExpression), expectedType)
}
}
case Success(ArrayT(itemT)) => {
for {
firstExp <- typeCheck(first, CountT, env, featureSet, tcParameters)

// TODO - we must ensure that the evaluator is not evaluating anything too complex here
// must be a "simple map" type situation
// can this be built into the evaluator?
firstObj <- Evaluator(firstExp.nExpression, env)

secondT = MapT(
TypeTransform(IndexT(firstObj), itemT),
MapConfig(RequireCompleteness, BasicMap)
)

secondExp <- typeCheck(second, secondT, env, featureSet, tcParameters)
} yield {
TypeCheckResponse(UCase(firstObj, secondExp.nExpression), expectedType)
}
}
case Success(TypeT) | Success(WildcardT(_)) => {
for {
result <- typeCheckCaseAsType(first, second, env.typeSystem.currentVersion, featureSet, env, tcParameters)
Expand Down Expand Up @@ -490,12 +500,15 @@ object TypeChecker {
): Outcome[Vector[(UntaggedObject, UntaggedObject)], String] = {
values match {
case KeyValueBinding(k, v) +: restOfValues => {
//println("Checking KEY: " + k + " -- " + typeTransform.keyType)
for {
resultKey <- typeCheckWithPatternMatching(k, typeTransform.keyType, env, externalFeatureSet, internalFeatureSet, tcParameters)

// Keys must be evaluated on the spot
foundKeyPattern <- Evaluator(resultKey.typeCheckResult, env)

//_ = println(s"keyPattern: $foundKeyPattern -- ${resultKey.newParams}")

untaggedTypeTransformKey = typeTransform.keyType.asUntagged
untaggedTypeTransformValue = typeTransform.valueType.asUntagged

Expand All @@ -509,6 +522,8 @@ object TypeChecker {
valueTypePatternUntagged = MakeSubstitution(untaggedTypeTransformValue, paramsToSubsitute)
valueTypePattern <- valueTypePatternUntagged.asType

//_ = println(s"About to check value: $v -- $valueTypePattern -- ${resultKey.newParams}")

// Now we want to type check the object, but we have to tell it what kind of map we're in
// in order to ensure that the right features are being used
objectFoundValue <- typeCheck(
Expand Down Expand Up @@ -546,6 +561,21 @@ object TypeChecker {
} yield underlyingT
}

def getCurrentUnderlyingType(name: String, params: UntaggedObject, env: Environment): Outcome[NewMapType, String] = {
for {
underlyingTypeInfo <- env.typeSystem.currentUnderlyingType(name)

parameterPattern = underlyingTypeInfo._1
genericUnderlyingType = underlyingTypeInfo._2

substitutions <- Evaluator.patternMatch(parameterPattern, params, StandardMatcher, env)

underlyingType = MakeSubstitution(genericUnderlyingType.asUntagged, substitutions)

underlyingT <- underlyingType.asType
} yield underlyingT
}

def getFinalUnderlyingType(nType: NewMapType, env: Environment): Outcome[NewMapType, String] = {
nType match {
case CustomT(name, params, typeSystemId) => {
Expand All @@ -554,6 +584,9 @@ object TypeChecker {
finalizeResult <- getFinalUnderlyingType(partialResultT, env)
} yield finalizeResult
}
case ArrayT(itemT) => {
getCurrentUnderlyingType("Array", itemT.asUntagged, env)
}
case _ => Success(nType)
}
}
Expand Down Expand Up @@ -661,6 +694,26 @@ object TypeChecker {
)
}
}
case (ConstructCaseParse(constructorP, input), Success(ArrayT(itemT))) if (patternMatchingAllowed) => {
for {
// TODO - update environment here
constructorTC <- typeCheckWithPatternMatching(constructorP, CountT, env, externalFeatureSet, internalFeatureSet, tcParameters)
constructor <- Evaluator(constructorTC.typeCheckResult, env)

inputTExpected = MapT(
TypeTransform(IndexT(constructor), itemT),
MapConfig(RequireCompleteness, BasicMap)
)

result <- typeCheckWithPatternMatching(input, inputTExpected, env, externalFeatureSet, internalFeatureSet, constructorTC.newParams)
} yield {
TypeCheckWithPatternMatchingResult(
UCase(constructor, result.typeCheckResult),
expectedType,
result.newParams
)
}
}
case (ConstructCaseParse(constructorP, input), Success(TypeT)) if (patternMatchingAllowed) => {
for {
// For now, the constructor will explicitly point to a generic case type
Expand All @@ -682,8 +735,16 @@ object TypeChecker {
tcParameters
)
} yield {
// TODO - this is an awkward hack given how we slip in the historical UUID.
// - Let's figure out if there's a better way to organize this.
val includeUuid = NewMapTypeSystem.isCustomType(name)

val uParams = if (includeUuid) {
UArray(result.typeCheckResult, UIndex(env.typeSystem.currentVersion))
} else result.typeCheckResult

TypeCheckWithPatternMatchingResult(
CustomT(name, result.typeCheckResult, env.typeSystem.currentVersion).asUntagged,
UCase(UIdentifier(name), uParams),
expectedType,
result.newParams
)
Expand Down
10 changes: 10 additions & 0 deletions src/main/scala/ai/newmap/interpreter/TypeConverter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ object TypeConverter {
IsTypeConvertibleResponse(Vector.empty, refinedEndingType, newParameters)
}
}
case (ArrayT(param1), ArrayT(param2)) => {
// TODO - this is really a copy of the customT situation above
for {
newParameters <- Evaluator.patternMatch(param2.asUntagged, param1.asUntagged, TypeMatcher, env)
} yield {
val refinedEndingType = endingType // TODO - recheck this!

IsTypeConvertibleResponse(Vector.empty, refinedEndingType, newParameters)
}
}
case _ if (startingType == endingType) => Success(emptyResponse)
case (SubtypeT(_, parentType, _), _) => {
isTypeConvertible(parentType, endingType, env)
Expand Down
21 changes: 13 additions & 8 deletions src/main/scala/ai/newmap/interpreter/UpdateCommandCalculator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,16 @@ object UpdateCommandCalculator {
Success(defaultUMap)
}*/
case CharacterT => Success(UCharacter('\u0000'))
case CustomT("Array", _, _) => Success(UCase(UIndex(0), UArray()))
case CustomT("String", _, _) => Success(UCase(UIndex(0), UArray())) // Replace this line with a conversion!
case _ => Failure(s"Type ${nType.displayString(env)} has no default value")
case ArrayT(_) => Success(UCase(UIndex(0), UArray()))
case CustomT(name, params, typeSystemId) => {
for {
underlying <- TypeChecker.getUnderlyingType(name, params, env, typeSystemId)
result <- getDefaultValueOfCommandTypeHardcoded(underlying, env)
} yield result
}
case _ => {
Failure(s"Type ${nType.displayString(env)} has no default value")
}
}
}

Expand Down Expand Up @@ -160,8 +167,7 @@ object UpdateCommandCalculator {
// Are we allowed to change an old parameter? Let's say sure.
Success(CaseT(parameterList, parentFieldType, featureSet))
}
// This should be custom defined
case CustomT("Array", nType, _) => nType.asType
case ArrayT(nType) => Success(nType)
case CustomT(typeName, params, typeSystemId) => {
for {
underlyingTypeInfo <- env.typeSystem.historicalUnderlyingType(typeName, typeSystemId)
Expand Down Expand Up @@ -305,7 +311,6 @@ object UpdateCommandCalculator {
uNewFunctionType = newFunctionObjectComponents._1
uNewFunctionMapping = newFunctionObjectComponents._2
} yield {

// Also upgrade the function itself
// TODO: I think the composition between uNewFunctionMaping and currentMapping needs to be handled better
NewMapObject(
Expand Down Expand Up @@ -343,7 +348,7 @@ object UpdateCommandCalculator {
command match {
case UCase(constructor, input) => {
for {
mapValues <- current.uObject.getMapBindings
mapValues <- current.uObject.getMapBindings()

// TODO - this part is currently only written for _default
// Params need to be updated!!
Expand All @@ -358,7 +363,7 @@ object UpdateCommandCalculator {
}
}
}
case nType@CustomT("Array", _, _) => {
case nType@ArrayT(_) => {
for {
untaggedResult <- current.uObject match {
case UCase(UIndex(length), UArray(values)) => {
Expand Down
11 changes: 1 addition & 10 deletions src/main/scala/ai/newmap/model/Environment.scala
Original file line number Diff line number Diff line change
Expand Up @@ -617,16 +617,7 @@ object Environment {
NewParamTypeCommand(
"Array",
Vector("T" -> TypeT),
CaseT(
UMap(Vector(UWildcard("i") ->
MapT(
TypeTransform(IndexT(ParamId("i")), ParamIdT("T")),
MapConfig(RequireCompleteness, SimpleFunction)
).asUntagged
)),
CountT,
SimpleFunction
)
ArrayT(ParamIdT("T"))
),
NewTypeCommand("Object", NewMapO.taggedObjectT),
NewVersionedStatementCommand("__FunctionSystem", FunctionalSystemT(Vector.empty)),
Expand Down
23 changes: 17 additions & 6 deletions src/main/scala/ai/newmap/model/NewMapType.scala
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,8 @@ object CommandOutput extends MapCompleteness {
override def getName: String = "CommandOutput"
}

// This is actually not a full map, but a pattern that may match a map
// The untagged object of this is going to be USingularMap
object MapPattern extends MapCompleteness {
override def getName: String = "MapPattern"
object PartialMap extends MapCompleteness {
override def getName: String = "PartialMap"
}

sealed abstract class MapFeatureSet {
Expand Down Expand Up @@ -208,6 +206,13 @@ case class FunctionalSystemT(
functionTypes: Vector[(UntaggedObject, UntaggedObject)]
) extends NewMapType

/**
* The values are cases, where the first item in the case is the length of the array, and the second is the case itself.
* This should probably be implemented as Custom types (CustomT).
* However, to start, it's probably easier to have them as explicit in the type system
*/
case class ArrayT(nType: NewMapType) extends NewMapType

case class CustomT(
name: String,
params: UntaggedObject,
Expand Down Expand Up @@ -253,6 +258,7 @@ object NewMapType {
UIdentifier(featureSet.getName)
)))
case FunctionalSystemT(functionTypes) => UCase(UIdentifier("FunctionalSystem"), UMap(functionTypes))
case ArrayT(nType) => UCase(UIdentifier("Array"), nType.asUntagged)
case CustomT(name, params, typeSystemId) => UCase(UIdentifier(name), UArray(params, UIndex(typeSystemId)))
case WildcardT(name) => UWildcard(name)
case ParamIdT(name) => ParamId(name)
Expand Down Expand Up @@ -379,6 +385,11 @@ object NewMapType {
}
case _ => Success(TypeTransformT(false))
}
case "Array" => {
for {
nType <- convertToNewMapType(params)
} yield ArrayT(nType)
}
case custom => params match {
case UArray(items) if items.length == 2 => {
val customParams = items(0)
Expand All @@ -400,8 +411,8 @@ object NewMapType {
case UWildcard(name) => Success(WildcardT(name))
case ParamId(name) => Success(ParamIdT(name))
case _ => {
//throw new Exception(s"Couldn't convert to NewMapType: $uType")
Failure(s"Couldn't convert to NewMapType: $uType")
throw new Exception(s"Couldn't convert to NewMapType: $uType")
//Failure(s"Couldn't convert to NewMapType: $uType")
}
}

Expand Down
Loading

0 comments on commit d6dbecd

Please sign in to comment.