diff --git a/backend/serialization/vanilla_LibCloud-TraceCloudStorage-CloudStorageFormat_simple.json b/backend/serialization/vanilla_LibCloud-TraceCloudStorage-CloudStorageFormat_simple.json index 3a732209bd..e1e1394985 100644 --- a/backend/serialization/vanilla_LibCloud-TraceCloudStorage-CloudStorageFormat_simple.json +++ b/backend/serialization/vanilla_LibCloud-TraceCloudStorage-CloudStorageFormat_simple.json @@ -68,7 +68,7 @@ 7, "testFn", 2, - "CyUbRjC0vaw", + "fMP2hdPemZc", { "DError": [ { diff --git a/backend/src/BuiltinCliHost/Libs/Cli.fs b/backend/src/BuiltinCliHost/Libs/Cli.fs index c75c6281e0..4323b80389 100644 --- a/backend/src/BuiltinCliHost/Libs/Cli.fs +++ b/backend/src/BuiltinCliHost/Libs/Cli.fs @@ -171,6 +171,7 @@ let fns : List = try match parsedScript with | Ok mod' -> + debuG "parsed" mod' match! execute state mod' symtable with | DInt i -> return Dval.resultOk (DInt i) | DError(_, e) -> return e |> RuntimeError.toDT |> Dval.resultError diff --git a/backend/src/BuiltinExecution/Libs/Float.fs b/backend/src/BuiltinExecution/Libs/Float.fs index 7be9b1eaa0..e1399315b1 100644 --- a/backend/src/BuiltinExecution/Libs/Float.fs +++ b/backend/src/BuiltinExecution/Libs/Float.fs @@ -55,6 +55,7 @@ let fns : List = fn = (function | _, _, [ DFloat a ] -> a |> Math.Floor |> int64 |> DInt |> Ply + | _ -> incorrectArgs ()) sqlSpec = NotYetImplemented previewable = Pure diff --git a/backend/src/BuiltinExecution/Libs/NoModule.fs b/backend/src/BuiltinExecution/Libs/NoModule.fs index 5647444add..d06603a07d 100644 --- a/backend/src/BuiltinExecution/Libs/NoModule.fs +++ b/backend/src/BuiltinExecution/Libs/NoModule.fs @@ -269,6 +269,7 @@ and equalsMatchPattern (pattern1 : MatchPattern) (pattern2 : MatchPattern) : boo let varA = TVariable "a" +let varB = TVariable "b" let types : List = [] let constants : List = [] @@ -304,6 +305,94 @@ let fns : List = deprecated = NotDeprecated } + { name = fn "timeUnitFn" 0 + typeParams = [ "resultType" ] + parameters = [ + Param.makeWithArgs + "fn" + (TFn(NEList.singleton TUnit, varA)) + "" + [ ] ] + returnType = TTuple(varA, TInt, []) + description = "Times a function that takes no args; returns the result and the duration" + fn = + (function + | state, _, [ DFnVal fn ] -> + uply { + // using System; + // using System.Diagnostics; + // using System.Threading; + let stopwatch = new System.Diagnostics.Stopwatch() + stopwatch.Start() + let! result = LibExecution.Interpreter.applyFnVal state 0UL fn [] (NEList.singleton DUnit) + stopwatch.Stop() + let duration = stopwatch.ElapsedMilliseconds + return DTuple(result, DInt duration, []) + } + | _ -> incorrectArgs ()) + sqlSpec = NotQueryable + previewable = Impure + deprecated = NotDeprecated } + + + { name = fn "timeUnitFnIgnoringResult" 0 + typeParams = [ "resultTypeToIgnore" ] + parameters = [ + Param.makeWithArgs + "fn" + (TFn(NEList.singleton TUnit, varA)) + "" + [ ] ] + returnType = TInt + description = "Times a function that takes no args; returns the result and the duration" + fn = + (function + | state, _, [ DFnVal fn ] -> + uply { + // using System; + // using System.Diagnostics; + // using System.Threading; + let stopwatch = new System.Diagnostics.Stopwatch() + stopwatch.Start() + let! _result = LibExecution.Interpreter.applyFnVal state 0UL fn [] (NEList.singleton DUnit) + stopwatch.Stop() + let duration = stopwatch.ElapsedMilliseconds + return DInt duration + } + | _ -> incorrectArgs ()) + sqlSpec = NotQueryable + previewable = Impure + deprecated = NotDeprecated } + + + { name = fn "timeFn" 0 + typeParams = [ ] + parameters = [ + Param.makeWithArgs + "fn" + (TFn(NEList.singleton varA, varB)) + "" + [ ] + Param.make "args" (TList varA) "" ] + returnType = TInt + description = "Times a function that takes no args; returns the result and the duration" + fn = + (function + | state, _, [ DFnVal fn; DList (_, firstArg :: additionalArgs) ] -> + uply { + let stopwatch = new System.Diagnostics.Stopwatch() + stopwatch.Start() + let! _result = LibExecution.Interpreter.applyFnVal state 0UL fn [] (NEList.ofList firstArg additionalArgs) + stopwatch.Stop() + let duration = stopwatch.ElapsedMilliseconds + return DInt duration + } + | _ -> incorrectArgs ()) + sqlSpec = NotQueryable + previewable = Impure + deprecated = NotDeprecated } + + { name = fn "unwrap" 0 typeParams = [] parameters = [ Param.make "value" (TVariable "optOrRes") "" ] diff --git a/backend/src/Cli/Cli.fs b/backend/src/Cli/Cli.fs index 29b4f3ecc1..f1d8141cda 100644 --- a/backend/src/Cli/Cli.fs +++ b/backend/src/Cli/Cli.fs @@ -53,7 +53,7 @@ let builtIns : RT.BuiltIns = fns = fns |> Map.fromListBy (fun fn -> fn.name) constants = constants |> Map.fromListBy (fun c -> c.name) } -let packageManager = LibCliExecution.PackageManager.packageManager +let packageManager = LibCloud.PackageManager.packageManager let state () = let program : RT.Program = @@ -106,6 +106,11 @@ let main (args : string[]) = initSerializers () packageManager.init.Result + LibService.Init.init "Cli" + LibService.Telemetry.Console.loadTelemetry + "Cli" + LibService.Telemetry.DontTraceDBQueries + (LibCloud.Init.waitForDB ()).Result let result = execute (Array.toList args) let result = result.Result @@ -119,6 +124,7 @@ let main (args : string[]) = match source with | RT.SourceID(tlid, id) -> $"(source: {tlid}, {id})" | RT.SourceNone -> "(source unknown)" + match (LibExecution.Execution.runtimeErrorToString state rte).Result with | RT.DString s -> System.Console.WriteLine $"Error {source}:\n {s}" | newErr -> diff --git a/backend/src/Cli/Cli.fsproj b/backend/src/Cli/Cli.fsproj index 1ad1b26da8..39ca391b5a 100644 --- a/backend/src/Cli/Cli.fsproj +++ b/backend/src/Cli/Cli.fsproj @@ -51,6 +51,8 @@ + + diff --git a/backend/src/LibExecution/Interpreter.fs b/backend/src/LibExecution/Interpreter.fs index fb06bde96c..83e430d87b 100644 --- a/backend/src/LibExecution/Interpreter.fs +++ b/backend/src/LibExecution/Interpreter.fs @@ -290,7 +290,7 @@ let rec eval' match List.tryFind Dval.isFake results with | Some fakeDval -> return fakeDval - | None -> return Dval.list valueTypeTODO results + | None -> return Dval.list ValueType.Unknown results | ETuple(_id, first, second, theRest) -> diff --git a/backend/src/LibParser/FSharpToWrittenTypes.fs b/backend/src/LibParser/FSharpToWrittenTypes.fs index bd822cfc2e..3d18d09aec 100644 --- a/backend/src/LibParser/FSharpToWrittenTypes.fs +++ b/backend/src/LibParser/FSharpToWrittenTypes.fs @@ -551,7 +551,11 @@ module Expr = (SynExpr.Record _ as expr), _) -> if List.length typeArgs <> 0 then - Exception.raiseInternal "Record should not have type args" [ "expr", expr ] + debuG "name" name + // why not? + Exception.raiseInternal + "Record should not have type args" + [ "expr", expr; "name", name ] match c expr with | WT.ERecord(id, typeName, fields) -> WT.ERecord(id, typeName, fields) diff --git a/backend/src/Prelude/Json.fs b/backend/src/Prelude/Json.fs index 58881a83c7..d2311ad68f 100644 --- a/backend/src/Prelude/Json.fs +++ b/backend/src/Prelude/Json.fs @@ -245,10 +245,11 @@ module Vanilla = System.Console.Write("error allowing Vanilla type") let assertSerializable (t : System.Type) : unit = - if not (isSerializable t) then - Exception.sendRollbarError - "Invalid serialization call to type not allowed: add `Json.Vanilla.allow()` to allow it to be serialized" - [ "type", string t ] + // if not (isSerializable t) then + // Exception.sendRollbarError + // "Invalid serialization call to type not allowed: add `Json.Vanilla.allow()` to allow it to be serialized" + // [ "type", string t ] + () let serialize (data : 'a) : string = diff --git a/backend/testfiles/execution/stdlib/float.dark b/backend/testfiles/execution/stdlib/float.dark index 534b012987..0ddfe86e6e 100644 --- a/backend/testfiles/execution/stdlib/float.dark +++ b/backend/testfiles/execution/stdlib/float.dark @@ -95,6 +95,7 @@ PACKAGE.Darklang.Stdlib.Float.clamp_v0 3.0 0.0 2.0 = PACKAGE.Darklang.Stdlib.Res 2.0 Builtin.Float.divide_v0 9.0 2.0 = 4.5 +Builtin.Float.divide_v0 1.0 0.0 = 4.5 9.0 / 2.0 = 4.5 17.0 / 3.3 = 5.151515152 @@ -170,6 +171,7 @@ Builtin.Float.roundTowardsZero 2147483647.000009 = 2147483647 Builtin.Float.sqrt_v0 25.0 = 5.0 Builtin.Float.sqrt_v0 0.0 = 0.0 +Builtin.Float.sqrt_v0 -1.0 == Builtin.Test.nan_v0 = 0.0 Builtin.Float.subtract_v0 1.0 0.2 = 0.8 diff --git a/packages/darklang/cli/cli.dark b/packages/darklang/cli/cli.dark index dde605ac5c..6b0e0e9e86 100644 --- a/packages/darklang/cli/cli.dark +++ b/packages/darklang/cli/cli.dark @@ -310,10 +310,12 @@ module Darklang = | Ok i -> i | Error e -> Builtin.print $"Error executing script {scriptPath}" - Builtin.print e.msg - e.metadata - |> Builtin.Dict.iter (fun (k, v) -> Builtin.print $" {k}: {v}") + Builtin.print ( + e + |> PACKAGE.Darklang.LanguageTools.RuntimeErrors.Error.CliError + |> PACKAGE.Darklang.LanguageTools.RuntimeErrors.Error.toString + ) 1 diff --git a/scripts/build/reload-packages b/scripts/build/reload-packages index 1d76a0d64a..e72b79a1ac 100755 --- a/scripts/build/reload-packages +++ b/scripts/build/reload-packages @@ -22,10 +22,10 @@ done if [[ "$TEST" == "true" ]]; then LOG_DB="${DARK_CONFIG_RUNDIR}/logs/test-packages-db.log" - LOG_CANVAS="${DARK_CONFIG_RUNDIR}/logs/test-packages-canvas.log" + # LOG_CANVAS="${DARK_CONFIG_RUNDIR}/logs/test-packages-canvas.log" else LOG_DB="${DARK_CONFIG_RUNDIR}/logs/packages-db.log" - LOG_CANVAS="${DARK_CONFIG_RUNDIR}/logs/packages-canvas.log" + # LOG_CANVAS="${DARK_CONFIG_RUNDIR}/logs/packages-canvas.log" fi @@ -50,10 +50,10 @@ echo -e "Loading packages into DB ${grey}($LOG_DB)${reset}" # done -if [[ "$TEST" != "true" ]]; then - # make sure the target canvas exists and is cleared - ./scripts/run-canvas-hack dark-packages +# if [[ "$TEST" != "true" ]]; then +# # make sure the target canvas exists and is cleared +# ./scripts/run-canvas-hack dark-packages - echo -e "Loading packages into Dark canvas ${grey}($LOG_CANVAS)${reset}" - ./scripts/run-local-exec load-packages-dark > $LOG_CANVAS 2>&1 -fi \ No newline at end of file +# echo -e "Loading packages into Dark canvas ${grey}($LOG_CANVAS)${reset}" +# ./scripts/run-local-exec load-packages-dark > $LOG_CANVAS 2>&1 +# fi \ No newline at end of file diff --git a/scripts/perf-analysis.dark b/scripts/perf-analysis.dark new file mode 100644 index 0000000000..d7789f5675 --- /dev/null +++ b/scripts/perf-analysis.dark @@ -0,0 +1,76 @@ +// things to bring up: +// - parsing TestInput yields an error "Record should not have type args" - why? +// +// - canvases can't currently be passed with root-level modules - OK to fix? +// (this affects scripts since those are parsed as canvases) +// (we've probably avoided this so no one tries to put an http handler in a submodule) +// +// - should we update parsing to allow for `fun () -> ...` +// currently we require `fun _ -> ...`, +// but I think it might be ok to interpret () as an expected unit arg? +// (wait for dmitry's PR) +// +// - (how) should timing fns be presented to end users? (e.g. `timeFn` in `Builtin`) +// +// - would it be useful to keep pursuing this? +// maybe store the results once in a while, and track them over time? +// - timespan? +// - extend datetime fns to include ms stuff + +type TestInput<'a> = + { label: String + fn: (Unit -> 'a) + expected: 'a } + +// type OptionRecordWrapper<'a> = +// { opt: Option<'a> } + +//OptionRecordWrapper { opt = Option.Option.None } + +// type TestResult<'a> = { inputLabel: String; actual: 'a; durationInMs: Float } + +let runTests<'a> (tests: List>) : Unit = + tests + |> PACKAGE.Darklang.Stdlib.List.iter (fun t -> + let (_actual, duration) = Builtin.timeUnitFn<'a> fn + // TODO: yell if actual <> expected + Builtin.print $"{input.label}: {Builtin.Float.toString duration}ms") + + +// -- Int -- +let runIntAddTests () : Unit = + runTests // is this requried if there's an explicit type param at fn decl? + [ TestInput + { label = "1 + 2" + fn = fun _ -> Builtin.Int.add 1 2 + expected = 3 } + TestInput + { label = "0 + 0" + fn = fun _ -> Builtin.Int.add 0 0 + expected = 0 } ] + +let runIntTests () : Unit = runIntAddTests () + + +// -- Float -- +// let runAddTests (): Unit = +// [ { label = "1.0 + 2.5"; fn = (fun _ -> Builtin.Float.add 1.0 2.5); expected = 3.5 } +// { label = "0.0 + 0.0"; fn = (fun _ -> Builtin.Float.add 0.0 0.0); expected = 0.0 } ] +// |> runTests + +let runFloatTests () : Unit = + // runAddTests() + () + +let runAll () = + runIntTests () + runFloatTests () + + + + +// TODO: ensure all functions are covered? (fetch them all, compare against ones tested, etc.) +// TODO: test failures +(runAll () + Builtin.print "tests have been run!" + 0) \ No newline at end of file