index.ts (6416B)
1 import { result } from "../../utility/result.js"; 2 import { Value, vLambda, vNumber, vString } from "../../value/index.js"; 3 import { SqError } from "../SqError.js"; 4 import { SqValueContext } from "../SqValueContext.js"; 5 import { SqArray } from "./SqArray.js"; 6 import { SqCalculator } from "./SqCalculator.js"; 7 import { SqDict } from "./SqDict.js"; 8 import { SqDistribution, wrapDistribution } from "./SqDistribution/index.js"; 9 import { SqDomain, wrapDomain } from "./SqDomain.js"; 10 import { SqInput, wrapInput } from "./SqInput.js"; 11 import { SqLambda } from "./SqLambda.js"; 12 import { SqPlot, wrapPlot } from "./SqPlot.js"; 13 import { SqScale, wrapScale } from "./SqScale.js"; 14 import { SqTableChart } from "./SqTableChart.js"; 15 16 export function wrapValue(value: Value, context?: SqValueContext) { 17 switch (value.type) { 18 case "Array": 19 return new SqArrayValue(value, context); 20 case "Bool": 21 return new SqBoolValue(value, context); 22 case "Date": 23 return new SqDateValue(value, context); 24 case "Dist": 25 return new SqDistributionValue(value, context); 26 case "Lambda": 27 return new SqLambdaValue(value, context); 28 case "Number": 29 return new SqNumberValue(value, context); 30 case "Dict": 31 return new SqDictValue(value, context); 32 case "String": 33 return new SqStringValue(value, context); 34 case "Plot": 35 return new SqPlotValue(value, context); 36 case "TableChart": 37 return new SqTableChartValue(value, context); 38 case "Calculator": 39 return new SqCalculatorValue(value, context); 40 case "Scale": 41 return new SqScaleValue(value, context); 42 case "TimeDuration": 43 return new SqTimeDurationValue(value, context); 44 case "Void": 45 return new SqVoidValue(value, context); 46 case "Domain": 47 return new SqDomainValue(value, context); 48 case "Input": 49 return new SqInputValue(value, context); 50 default: 51 throw new Error(`Unknown value ${JSON.stringify(value satisfies never)}`); 52 } 53 } 54 55 export abstract class SqAbstractValue<Type extends string, JSType> { 56 abstract tag: Type; 57 58 constructor( 59 public _value: Extract<Value, { type: Type }>, 60 public context?: SqValueContext 61 ) {} 62 63 toString() { 64 return this._value.toString(); 65 } 66 67 publicName() { 68 return this._value.publicName; 69 } 70 71 abstract asJS(): JSType; 72 } 73 74 export class SqArrayValue extends SqAbstractValue<"Array", unknown[]> { 75 tag = "Array" as const; 76 77 get value() { 78 return new SqArray(this._value.value, this.context); 79 } 80 81 asJS(): unknown[] { 82 return this.value.getValues().map((value) => value.asJS()); 83 } 84 } 85 86 export class SqBoolValue extends SqAbstractValue<"Bool", boolean> { 87 tag = "Bool" as const; 88 89 get value(): boolean { 90 return this._value.value; 91 } 92 93 asJS() { 94 return this.value; 95 } 96 } 97 98 export class SqDateValue extends SqAbstractValue<"Date", Date> { 99 tag = "Date" as const; 100 101 get value(): Date { 102 return this._value.value; 103 } 104 105 asJS() { 106 return this.value; 107 } 108 } 109 110 export class SqDistributionValue extends SqAbstractValue< 111 "Dist", 112 SqDistribution 113 > { 114 tag = "Dist" as const; 115 116 get value() { 117 return wrapDistribution(this._value.value); 118 } 119 120 asJS() { 121 return this.value; // should we return BaseDist instead? 122 } 123 } 124 125 export class SqLambdaValue extends SqAbstractValue<"Lambda", SqLambda> { 126 tag = "Lambda" as const; 127 128 static create(value: SqLambda) { 129 return new SqLambdaValue(vLambda(value._value)); 130 } 131 132 get value() { 133 return new SqLambda(this._value.value, this.context); 134 } 135 136 asJS() { 137 return this.value; // SqLambda is nicer than internal Lambda, so we use that 138 } 139 } 140 141 export class SqNumberValue extends SqAbstractValue<"Number", number> { 142 tag = "Number" as const; 143 144 static create(value: number) { 145 return new SqNumberValue(vNumber(value)); 146 } 147 148 get value(): number { 149 return this._value.value; 150 } 151 152 asJS() { 153 return this.value; 154 } 155 } 156 157 export class SqDictValue extends SqAbstractValue<"Dict", Map<string, unknown>> { 158 tag = "Dict" as const; 159 160 get value() { 161 return new SqDict(this._value.value, this.context); 162 } 163 164 asJS(): Map<string, unknown> { 165 return new Map(this.value.entries().map(([k, v]) => [k, v.asJS()])); // this is a native Map, not immutable Map 166 } 167 } 168 169 export class SqStringValue extends SqAbstractValue<"String", string> { 170 tag = "String" as const; 171 172 static create(value: string) { 173 return new SqStringValue(vString(value)); 174 } 175 176 get value(): string { 177 return this._value.value; 178 } 179 180 asJS() { 181 return this.value; 182 } 183 } 184 185 export class SqTimeDurationValue extends SqAbstractValue< 186 "TimeDuration", 187 number 188 > { 189 tag = "TimeDuration" as const; 190 191 get value() { 192 return this._value.value; 193 } 194 195 asJS() { 196 return this._value.value; 197 } 198 } 199 200 export class SqPlotValue extends SqAbstractValue<"Plot", SqPlot> { 201 tag = "Plot" as const; 202 203 get value() { 204 return wrapPlot(this._value.value, this.context); 205 } 206 207 asJS() { 208 return this.value; 209 } 210 } 211 export class SqTableChartValue extends SqAbstractValue< 212 "TableChart", 213 SqTableChart 214 > { 215 tag = "TableChart" as const; 216 217 get value() { 218 return new SqTableChart(this._value.value, this.context); 219 } 220 221 asJS() { 222 return this.value; 223 } 224 } 225 export class SqCalculatorValue extends SqAbstractValue< 226 "Calculator", 227 SqCalculator 228 > { 229 tag = "Calculator" as const; 230 231 get value() { 232 return new SqCalculator(this._value.value, this.context); 233 } 234 235 asJS() { 236 return this.value; 237 } 238 } 239 240 export class SqScaleValue extends SqAbstractValue<"Scale", SqScale> { 241 tag = "Scale" as const; 242 243 get value() { 244 return wrapScale(this._value.value); 245 } 246 247 asJS() { 248 return this.value; 249 } 250 } 251 252 export class SqInputValue extends SqAbstractValue<"Input", SqInput> { 253 tag = "Input" as const; 254 255 get value() { 256 return wrapInput(this._value.value); 257 } 258 259 asJS() { 260 return this.value; 261 } 262 } 263 264 export class SqVoidValue extends SqAbstractValue<"Void", null> { 265 tag = "Void" as const; 266 267 get value() { 268 return null; 269 } 270 271 asJS() { 272 return null; 273 } 274 } 275 276 export class SqDomainValue extends SqAbstractValue<"Domain", SqDomain> { 277 tag = "Domain" as const; 278 279 get value() { 280 return wrapDomain(this._value.value); 281 } 282 283 asJS() { 284 return this.value; 285 } 286 } 287 288 export type SqValue = ReturnType<typeof wrapValue>; 289 290 export function toStringResult(result: result<SqValue, SqError>) { 291 return `${result.ok ? "Ok" : "Error"}(${result.value.toString()})`; 292 }