packages feed

zeolite-lang 0.18.0.1 → 0.18.1.0

raw patch · 20 files changed

+642/−28 lines, 20 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Types.Procedure: isAssignableDiscard :: Assignable c -> Bool

Files

ChangeLog.md view
@@ -1,5 +1,23 @@ # Revision history for zeolite-lang +## 0.18.1.0  -- 2021-10-19++### Language++* **[fix]** Fixes issue with explicit return discards skipping generation of+  function calls. Previously, `_ <- foo()` skipped generating the call to `foo`.++### Libraries++* **[new]** Adds `RandomExponential`, `RandomGaussian`, and `RandomUniform` to+  `lib/math` for generating random `Float` values.++* **[new]** Adds `Realtime.sleepSecondsPrecise` function to allow sleeps that+  are more precise than the kernel's latency.++* **[new]** Adds `checkGreaterThan` and `checkLessThan` to `Testing` in+  `lib/testing`.+ ## 0.18.0.0  -- 2021-08-01  ### Compiler CLI
lib/math/.zeolite-module view
@@ -10,5 +10,17 @@     source: "lib/math/src/Extension_Math.cpp"     categories: [Math]   }+  category_source {+    source: "lib/math/src/Extension_RandomExponential.cpp"+    categories: [RandomExponential]+  }+  category_source {+    source: "lib/math/src/Extension_RandomGaussian.cpp"+    categories: [RandomGaussian]+  }+  category_source {+    source: "lib/math/src/Extension_RandomUniform.cpp"+    categories: [RandomUniform]+  } ] mode: incremental {}
+ lib/math/random.0rp view
@@ -0,0 +1,46 @@+/* -----------------------------------------------------------------------------+Copyright 2021 Kevin P. Barry++Licensed under the Apache License, Version 2.0 (the "License");+you may not use this file except in compliance with the License.+You may obtain a copy of the License at++    http://www.apache.org/licenses/LICENSE-2.0++Unless required by applicable law or agreed to in writing, software+distributed under the License is distributed on an "AS IS" BASIS,+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+See the License for the specific language governing permissions and+limitations under the License.+----------------------------------------------------------------------------- */++// Author: Kevin P. Barry [ta0kira@gmail.com]++// Generates values of type #x.+@value interface Generator<|#x> {+  generate () -> (#x)+}++// Generates exponentially-distributed Float values.+concrete RandomExponential {+  refines Generator<Float>++  // Creates a new generator with the specified lambda value.+  @type new (Float) -> (Generator<Float>)+}++// Generates Gaussian-distributed Float values.+concrete RandomGaussian {+  refines Generator<Float>++  // Creates a new generator with the specified mean and standard deviation.+  @type new (Float,Float) -> (Generator<Float>)+}++// Generates uniformly-distributed Float values.+concrete RandomUniform {+  refines Generator<Float>++  // Creates a new generator with the specified min and max values.+  @type new (Float,Float) -> (Generator<Float>)+}
+ lib/math/random.0rt view
@@ -0,0 +1,125 @@+/* -----------------------------------------------------------------------------+Copyright 2021 Kevin P. Barry++Licensed under the Apache License, Version 2.0 (the "License");+you may not use this file except in compliance with the License.+You may obtain a copy of the License at++    http://www.apache.org/licenses/LICENSE-2.0++Unless required by applicable law or agreed to in writing, software+distributed under the License is distributed on an "AS IS" BASIS,+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+See the License for the specific language governing permissions and+limitations under the License.+----------------------------------------------------------------------------- */++// Author: Kevin P. Barry [ta0kira@gmail.com]++testcase "valid instantiations" {+  success+}++unittest exponential {+  Generator<Float> random <- RandomExponential.new(1.0)+  Float value <- random.generate()+}++unittest gaussian {+  Generator<Float> random <- RandomGaussian.new(0.0,1.0)+  Float value <- random.generate()+}++unittest uniform {+  Generator<Float> random <- RandomUniform.new(0.0,1.0)+  Float value <- random.generate()+}+++testcase "negative lambda in exponential" {+  crash+  require "lambda"+  require "-1"+}++unittest test {+  Generator<Float> random <- RandomExponential.new(-1.0)+}+++testcase "negative standard deviation in gaussian" {+  crash+  require "standard deviation"+  require "-1"+}++unittest test {+  Generator<Float> random <- RandomGaussian.new(0.0,-1.0)+}+++testcase "empty range in uniform" {+  crash+  require "range"+  require "0,-1"+}++unittest test {+  Generator<Float> random <- RandomUniform.new(0.0,-1.0)+}+++testcase "distribution sanity checks" {+  success+}++unittest exponential {+  Int count <- 10000+  Float lambda <- 10.0+  $ReadOnly[count,lambda]$++  Generator<Float> random <- RandomExponential.new(lambda)++  Float sum <- 0.0+  traverse (Counter.zeroIndexed(count) -> _) {+    Float value <- random.generate()+    \ Testing.checkGreaterThan<?>(value,0.0)+    sum <- sum+value+  }++  \ Testing.checkBetween<?>(sum/count.asFloat(),0.9/lambda,1.1/lambda)+}++unittest gaussian {+  Int count <- 10000+  Float mean <- 100.0+  Float sd <- 1.0+  $ReadOnly[count,mean,sd]$++  Generator<Float> random <- RandomGaussian.new(mean,sd)++  Float sum <- 0.0+  traverse (Counter.zeroIndexed(count) -> _) {+    sum <- sum+random.generate()+  }++  \ Testing.checkBetween<?>(sum/count.asFloat(),mean-0.1*sd,mean+0.1*sd)+}++unittest uniform {+  Int count <- 10000+  Float min <- -11.0+  Float max <- 5.0+  $ReadOnly[count,min,max]$++  Generator<Float> random <- RandomUniform.new(min,max)++  Float sum <- 0.0+  traverse (Counter.zeroIndexed(count) -> _) {+    Float value <- random.generate()+    \ Testing.checkBetween<?>(value,min,max)+    sum <- sum+value+  }++  \ Testing.checkBetween<?>(sum/count.asFloat(),min-0.1*(max-min),max-0.1*(max-min))+}
+ lib/math/src/Extension_RandomExponential.cpp view
@@ -0,0 +1,81 @@+/* -----------------------------------------------------------------------------+Copyright 2021 Kevin P. Barry++Licensed under the Apache License, Version 2.0 (the "License");+you may not use this file except in compliance with the License.+You may obtain a copy of the License at++    http://www.apache.org/licenses/LICENSE-2.0++Unless required by applicable law or agreed to in writing, software+distributed under the License is distributed on an "AS IS" BASIS,+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+See the License for the specific language governing permissions and+limitations under the License.+----------------------------------------------------------------------------- */++// Author: Kevin P. Barry [ta0kira@gmail.com]++#include <random>++#include "category-source.hpp"+#include "Streamlined_RandomExponential.hpp"+#include "Category_Float.hpp"+#include "Category_Generator.hpp"+#include "Category_RandomExponential.hpp"+#include "Category_RandomUniform.hpp"++#ifdef ZEOLITE_PUBLIC_NAMESPACE+namespace ZEOLITE_PUBLIC_NAMESPACE {+#endif  // ZEOLITE_PUBLIC_NAMESPACE++BoxedValue CreateValue_RandomExponential(S<Type_RandomExponential> parent, const ValueTuple& args);++struct ExtCategory_RandomExponential : public Category_RandomExponential {+};++struct ExtType_RandomExponential : public Type_RandomExponential {+  inline ExtType_RandomExponential(Category_RandomExponential& p, Params<0>::Type params) : Type_RandomExponential(p, params) {}++  ReturnTuple Call_new(const S<TypeInstance>& Param_self, const ParamTuple& params, const ValueTuple& args) final {+    TRACE_FUNCTION("RandomExponential.new")+    const PrimFloat Var_arg1 = (args.At(0)).AsFloat();+    if (Var_arg1 <= 0) {+      FAIL() << "Invalid lambda " << Var_arg1;+    }+    return ReturnTuple(CreateValue_RandomExponential(shared_from_this(), args));+  }+};++struct ExtValue_RandomExponential : public Value_RandomExponential {+  inline ExtValue_RandomExponential(S<Type_RandomExponential> p, const ValueTuple& args)+    : Value_RandomExponential(p),+      distribution_(args.At(0).AsFloat()) {}++  ReturnTuple Call_generate(const BoxedValue& Var_self, const ParamTuple& params, const ValueTuple& args) final {+    TRACE_FUNCTION("RandomExponential.generate")+    return ReturnTuple(Box_Float(distribution_(generator_)));+  }++  std::default_random_engine generator_;+  std::exponential_distribution<double> distribution_;+};++Category_RandomExponential& CreateCategory_RandomExponential() {+  static auto& category = *new ExtCategory_RandomExponential();+  return category;+}++S<Type_RandomExponential> CreateType_RandomExponential(Params<0>::Type params) {+  static const auto cached = S_get(new ExtType_RandomExponential(CreateCategory_RandomExponential(), Params<0>::Type()));+  return cached;+}++BoxedValue CreateValue_RandomExponential(S<Type_RandomExponential> parent, const ValueTuple& args) {+  return BoxedValue(new ExtValue_RandomExponential(parent, args));+}++#ifdef ZEOLITE_PUBLIC_NAMESPACE+}  // namespace ZEOLITE_PUBLIC_NAMESPACE+using namespace ZEOLITE_PUBLIC_NAMESPACE;+#endif  // ZEOLITE_PUBLIC_NAMESPACE
+ lib/math/src/Extension_RandomGaussian.cpp view
@@ -0,0 +1,82 @@+/* -----------------------------------------------------------------------------+Copyright 2021 Kevin P. Barry++Licensed under the Apache License, Version 2.0 (the "License");+you may not use this file except in compliance with the License.+You may obtain a copy of the License at++    http://www.apache.org/licenses/LICENSE-2.0++Unless required by applicable law or agreed to in writing, software+distributed under the License is distributed on an "AS IS" BASIS,+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+See the License for the specific language governing permissions and+limitations under the License.+----------------------------------------------------------------------------- */++// Author: Kevin P. Barry [ta0kira@gmail.com]++#include <random>++#include "category-source.hpp"+#include "Streamlined_RandomGaussian.hpp"+#include "Category_Float.hpp"+#include "Category_Generator.hpp"+#include "Category_RandomGaussian.hpp"+#include "Category_RandomUniform.hpp"++#ifdef ZEOLITE_PUBLIC_NAMESPACE+namespace ZEOLITE_PUBLIC_NAMESPACE {+#endif  // ZEOLITE_PUBLIC_NAMESPACE++BoxedValue CreateValue_RandomGaussian(S<Type_RandomGaussian> parent, const ValueTuple& args);++struct ExtCategory_RandomGaussian : public Category_RandomGaussian {+};++struct ExtType_RandomGaussian : public Type_RandomGaussian {+  inline ExtType_RandomGaussian(Category_RandomGaussian& p, Params<0>::Type params) : Type_RandomGaussian(p, params) {}++  ReturnTuple Call_new(const S<TypeInstance>& Param_self, const ParamTuple& params, const ValueTuple& args) final {+    TRACE_FUNCTION("RandomGaussian.new")+    const PrimFloat Var_arg1 = (args.At(0)).AsFloat();+    const PrimFloat Var_arg2 = (args.At(1)).AsFloat();+    if (Var_arg2 <= 0) {+      FAIL() << "Invalid standard deviation " << Var_arg2;+    }+    return ReturnTuple(CreateValue_RandomGaussian(shared_from_this(), args));+  }+};++struct ExtValue_RandomGaussian : public Value_RandomGaussian {+  inline ExtValue_RandomGaussian(S<Type_RandomGaussian> p, const ValueTuple& args)+    : Value_RandomGaussian(p),+      distribution_(args.At(0).AsFloat(), args.At(1).AsFloat()) {}++  ReturnTuple Call_generate(const BoxedValue& Var_self, const ParamTuple& params, const ValueTuple& args) final {+    TRACE_FUNCTION("RandomGaussian.generate")+    return ReturnTuple(Box_Float(distribution_(generator_)));+  }++  std::default_random_engine generator_;+  std::normal_distribution<double> distribution_;+};++Category_RandomGaussian& CreateCategory_RandomGaussian() {+  static auto& category = *new ExtCategory_RandomGaussian();+  return category;+}++S<Type_RandomGaussian> CreateType_RandomGaussian(Params<0>::Type params) {+  static const auto cached = S_get(new ExtType_RandomGaussian(CreateCategory_RandomGaussian(), Params<0>::Type()));+  return cached;+}++BoxedValue CreateValue_RandomGaussian(S<Type_RandomGaussian> parent, const ValueTuple& args) {+  return BoxedValue(new ExtValue_RandomGaussian(parent, args));+}++#ifdef ZEOLITE_PUBLIC_NAMESPACE+}  // namespace ZEOLITE_PUBLIC_NAMESPACE+using namespace ZEOLITE_PUBLIC_NAMESPACE;+#endif  // ZEOLITE_PUBLIC_NAMESPACE
+ lib/math/src/Extension_RandomUniform.cpp view
@@ -0,0 +1,81 @@+/* -----------------------------------------------------------------------------+Copyright 2021 Kevin P. Barry++Licensed under the Apache License, Version 2.0 (the "License");+you may not use this file except in compliance with the License.+You may obtain a copy of the License at++    http://www.apache.org/licenses/LICENSE-2.0++Unless required by applicable law or agreed to in writing, software+distributed under the License is distributed on an "AS IS" BASIS,+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+See the License for the specific language governing permissions and+limitations under the License.+----------------------------------------------------------------------------- */++// Author: Kevin P. Barry [ta0kira@gmail.com]++#include <random>++#include "category-source.hpp"+#include "Streamlined_RandomUniform.hpp"+#include "Category_Float.hpp"+#include "Category_Generator.hpp"+#include "Category_RandomUniform.hpp"++#ifdef ZEOLITE_PUBLIC_NAMESPACE+namespace ZEOLITE_PUBLIC_NAMESPACE {+#endif  // ZEOLITE_PUBLIC_NAMESPACE++BoxedValue CreateValue_RandomUniform(S<Type_RandomUniform> parent, const ValueTuple& args);++struct ExtCategory_RandomUniform : public Category_RandomUniform {+};++struct ExtType_RandomUniform : public Type_RandomUniform {+  inline ExtType_RandomUniform(Category_RandomUniform& p, Params<0>::Type params) : Type_RandomUniform(p, params) {}++  ReturnTuple Call_new(const S<TypeInstance>& Param_self, const ParamTuple& params, const ValueTuple& args) final {+    TRACE_FUNCTION("RandomUniform.new")+    const PrimFloat Var_arg1 = (args.At(0)).AsFloat();+    const PrimFloat Var_arg2 = (args.At(1)).AsFloat();+    if (Var_arg2 <= Var_arg1) {+      FAIL() << "Invalid range (" << Var_arg1 << "," << Var_arg2 << ")";+    }+    return ReturnTuple(CreateValue_RandomUniform(shared_from_this(), args));+  }+};++struct ExtValue_RandomUniform : public Value_RandomUniform {+  inline ExtValue_RandomUniform(S<Type_RandomUniform> p, const ValueTuple& args)+    : Value_RandomUniform(p),+      distribution_(args.At(0).AsFloat(), args.At(1).AsFloat()) {}++  ReturnTuple Call_generate(const BoxedValue& Var_self, const ParamTuple& params, const ValueTuple& args) final {+    TRACE_FUNCTION("RandomUniform.generate")+    return ReturnTuple(Box_Float(distribution_(generator_)));+  }++  std::default_random_engine generator_;+  std::uniform_real_distribution<double> distribution_;+};++Category_RandomUniform& CreateCategory_RandomUniform() {+  static auto& category = *new ExtCategory_RandomUniform();+  return category;+}++S<Type_RandomUniform> CreateType_RandomUniform(Params<0>::Type params) {+  static const auto cached = S_get(new ExtType_RandomUniform(CreateCategory_RandomUniform(), Params<0>::Type()));+  return cached;+}++BoxedValue CreateValue_RandomUniform(S<Type_RandomUniform> parent, const ValueTuple& args) {+  return BoxedValue(new ExtValue_RandomUniform(parent, args));+}++#ifdef ZEOLITE_PUBLIC_NAMESPACE+}  // namespace ZEOLITE_PUBLIC_NAMESPACE+using namespace ZEOLITE_PUBLIC_NAMESPACE;+#endif  // ZEOLITE_PUBLIC_NAMESPACE
lib/testing/helpers.0rp view
@@ -68,4 +68,38 @@     #x defines Equals<#x>     #x defines LessThan<#x>   (#x,#x,#x) -> ()++  // Check that the value is above the limit. Crashes if it is not in the range.+  //+  // Args:+  // - #x: Actual value.+  // - #x: Lower bound.+  //+  // Notes:+  // - This could be done without Equals, except that some types have+  //   "undefined" values (e.g., NaN, for Float) that prevent inferring equality+  //   from less-than comparisons.+  // - This comparison doesn't allow the value to equal the bound.+  @type checkGreaterThan<#x>+    #x requires Formatted+    #x defines Equals<#x>+    #x defines LessThan<#x>+  (#x,#x) -> ()++  // Check that the value is below the limit. Crashes if it is not in the range.+  //+  // Args:+  // - #x: Actual value.+  // - #x: Upper bound.+  //+  // Notes:+  // - This could be done without Equals, except that some types have+  //   "undefined" values (e.g., NaN, for Float) that prevent inferring equality+  //   from less-than comparisons.+  // - This comparison doesn't allow the value to equal the bound.+  @type checkLessThan<#x>+    #x requires Formatted+    #x defines Equals<#x>+    #x defines LessThan<#x>+  (#x,#x) -> () }
lib/testing/helpers.0rx view
@@ -76,6 +76,26 @@     }   } +  checkGreaterThan (x,l) {+    if (lessEquals<?>(x,l)) {+      fail(String.builder()+          .append(x.formatted())+          .append(" is not greater than ")+          .append(l.formatted())+          .build())+    }+  }++  checkLessThan (x,h) {+    if (lessEquals<?>(h,x)) {+      fail(String.builder()+          .append(x.formatted())+          .append(" is not less than ")+          .append(h.formatted())+          .build())+    }+  }+   @type lessEquals<#x>     #x defines Equals<#x>     #x defines LessThan<#x>
lib/testing/tests.0rt view
@@ -138,3 +138,43 @@ unittest test {   \ Testing.checkBetween<?>(14,15,13) }+++testcase "checkGreaterThan success" {+  success+}++unittest test {+  \ Testing.checkGreaterThan<?>(13,11)+}+++testcase "checkGreaterThan fail" {+  crash+  require stderr "13"+  require stderr "14"+}++unittest test {+  \ Testing.checkGreaterThan<?>(13,14)+}+++testcase "checkLessThan success" {+  success+}++unittest test {+  \ Testing.checkLessThan<?>(13,14)+}+++testcase "checkLessThan fail" {+  crash+  require stderr "13"+  require stderr "11"+}++unittest test {+  \ Testing.checkLessThan<?>(13,11)+}
lib/thread/src/Extension_Realtime.cpp view
@@ -23,12 +23,17 @@  #include <chrono> #include <iomanip>+#include <thread>  #include "category-source.hpp" #include "Streamlined_Realtime.hpp" #include "Category_Float.hpp" #include "Category_Realtime.hpp" +#ifndef SLEEP_SPINLOCK_LIMIT+#define SLEEP_SPINLOCK_LIMIT 0.001+#endif+ #ifdef ZEOLITE_PUBLIC_NAMESPACE namespace ZEOLITE_PUBLIC_NAMESPACE { #endif  // ZEOLITE_PUBLIC_NAMESPACE@@ -42,18 +47,34 @@   ReturnTuple Call_sleepSeconds(const S<TypeInstance>& Param_self, const ParamTuple& params, const ValueTuple& args) final {     TRACE_FUNCTION("Realtime.sleepSeconds")     const PrimFloat Var_arg1 = (args.At(0)).AsFloat();-    if (Var_arg1 < 0) {-      FAIL() << "Bad wait time " << Var_arg1;+    if (Var_arg1 > 0) {+      std::this_thread::sleep_for(std::chrono::duration<double>(Var_arg1));     }-    struct timespec timeout{ (int) trunc(Var_arg1), (int) (1000000000.0 * (Var_arg1-trunc(Var_arg1))) };-    struct timespec remainder;-    while (nanosleep(&timeout, &remainder) != 0) {-      if (errno == EINTR) {-        timeout = remainder;+    return ReturnTuple();+  }++  ReturnTuple Call_sleepSecondsPrecise(const S<TypeInstance>& Param_self, const ParamTuple& params, const ValueTuple& args) final {+    TRACE_FUNCTION("Realtime.sleepSecondsPrecise")+    const PrimFloat Var_arg1 = (args.At(0)).AsFloat();++    const auto spinlock_limit = std::chrono::duration<double>(SLEEP_SPINLOCK_LIMIT);++    const auto target_time =+      std::chrono::high_resolution_clock::now().time_since_epoch() ++      std::chrono::duration<double>(Var_arg1);++    while (true) {+      const auto now = std::chrono::high_resolution_clock::now().time_since_epoch();+      if (now >= target_time) break;+      const auto sleep_time = target_time - now;+      if (sleep_time <= spinlock_limit) {+        while (std::chrono::high_resolution_clock::now().time_since_epoch() < target_time);+        break;       } else {-        FAIL() << "Error sleeping: " << strerror(errno) << " (error " << errno << ")";+        std::this_thread::sleep_for(sleep_time - spinlock_limit);       }     }+     return ReturnTuple();   } 
lib/thread/time.0rp view
@@ -21,6 +21,9 @@   // Sleep for the given number of seconds.   @type sleepSeconds (Float) -> () +  // Sleep for the given number of seconds, with more precision.+  @type sleepSecondsPrecise (Float) -> ()+   // Get a timestamp from a monotonic clock.   //   // Notes:
lib/thread/time.0rt view
@@ -16,22 +16,24 @@  // Author: Kevin P. Barry [ta0kira@gmail.com] -testcase "negative sleepSeconds() crashes" {-  crash-  require "-0\.1"+testcase "zero sleep is allowed" {+  success } -unittest test {-  \ Realtime.sleepSeconds(-0.1)+unittest zeroSleep {+  \ Realtime.sleepSeconds(0.0) } +unittest negativeSleep {+  \ Realtime.sleepSeconds(-0.1)+} -testcase "zero sleepSeconds() is allowed" {-  success+unittest zeroPrecise {+  \ Realtime.sleepSecondsPrecise(0.0) } -unittest test {-  \ Realtime.sleepSeconds(0.0)+unittest negativePrecise {+  \ Realtime.sleepSecondsPrecise(-0.1) }  @@ -46,14 +48,32 @@ }  +testcase "sleepSecondsPrecise() does not interfere with test timeout" {+  crash+  require "signal 14"+  timeout 1+}++unittest test {+  \ Realtime.sleepSecondsPrecise(5.0)+}++ testcase "monoSeconds() diff is somewhat accurate" {   success   timeout 2 } -unittest test {+unittest testSleep {   Float start <- Realtime.monoSeconds()   \ Realtime.sleepSeconds(0.5)   Float stop <- Realtime.monoSeconds()-  \ Testing.checkBetween<?>(stop-start,0.5,0.75)+  \ Testing.checkBetween<?>(stop-start,0.5,0.6)+}++unittest testPrecise {+  Float start <- Realtime.monoSeconds()+  \ Realtime.sleepSecondsPrecise(0.5)+  Float stop <- Realtime.monoSeconds()+  \ Testing.checkBetween<?>(stop-start,0.5,0.51) }
src/CompilerCxx/CxxFiles.hs view
@@ -725,7 +725,7 @@ createFunctionDispatch :: CategoryName -> SymbolScope -> [ScopedFunction c] -> CompiledData [String] createFunctionDispatch n s fs = function where   function-    | null filtered = onlyCode $ "{ " ++ fallback ++ " }"+    | null filtered = onlyCode fallback     | otherwise = onlyCodes $ [typedef] ++ concat (map table $ byCategory) ++ metaTable ++ select   filtered = filter ((== s) . sfScope) fs   flatten f = f:(concat $ map flatten $ sfMerges f)
src/CompilerCxx/Procedure.hs view
@@ -279,7 +279,7 @@   _ <- processPairsT alwaysPair (fmap assignableName as) ts   _ <- processPairsT (createVariable r fa) as ts   maybeSetTrace c-  variableTypes <- sequence $ map (uncurry getVariableType) $ zip (pValues as) (pValues ts)+  variableTypes <- sequence $ map getVariableType (pValues as)   assignAll (zip3 ([0..] :: [Int]) variableTypes (pValues as)) e'   where     message = "In assignment at " ++ formatFullContext c@@ -288,11 +288,11 @@       csWrite ["{","const auto r = " ++ useAsReturns e2 ++ ";"]       sequence_ $ map assignMulti vs       csWrite ["}"]-    getVariableType (CreateVariable _ t _) _ = return t-    getVariableType (ExistingVariable (InputValue c2 n)) _ = do+    getVariableType (CreateVariable _ t _) = return t+    getVariableType (ExistingVariable (InputValue c2 n)) = do       (VariableValue _ _ t _) <- csGetVariable (UsedVariable c2 n)       return t-    getVariableType (ExistingVariable (DiscardInput _)) t = return t+    getVariableType _ = return undefined     createVariable r fa (CreateVariable c2 t1 n) t2 =       "In creation of " ++ show n ++ " at " ++ formatFullContext c2 ??> do         self <- autoSelfType@@ -315,7 +315,8 @@       (VariableValue _ s _ _) <- csGetVariable (UsedVariable c2 n)       scoped <- autoScope s       csWrite [scoped ++ variableName n ++ " = " ++ writeStoredVariable t e2 ++ ";"]-    assignSingle _ _ = return ()+    assignSingle (_,_,ExistingVariable (DiscardInput _)) e2 = do+      csWrite ["(void)" ++ useAsWhatever e2 ++ ";"]     assignMulti (i,t,CreateVariable _ _ n) =       csWrite [variableName n ++ " = " ++                writeStoredVariable t (UnwrappedSingle $ "r.At(" ++ show i ++ ")") ++ ";"]
src/Parser/Procedure.hs view
@@ -104,7 +104,7 @@       return $ InputValue [c] v     discard = do       c <- getSourceContext-      sepAfter (string_ "_")+      sepAfter_ kwIgnore       return $ DiscardInput [c]  instance ParseFromSource (OutputValue SourceContext) where
src/Types/Procedure.hs view
@@ -51,6 +51,7 @@   getOperatorContext,   getOperatorName,   getStatementContext,+  isAssignableDiscard,   isDiscardedInput,   isFunctionOperator,   isNoTrace,@@ -203,6 +204,10 @@ assignableName (CreateVariable _ _ n)              = n assignableName (ExistingVariable (InputValue _ n)) = n assignableName _                                   = discardInputName++isAssignableDiscard :: Assignable c -> Bool+isAssignableDiscard (CreateVariable _ _ _) = False+isAssignableDiscard (ExistingVariable v)   = isDiscardedInput v  data VoidExpression c =   Conditional (IfElifElse c) |
tests/leak-check/README.md view
@@ -58,8 +58,12 @@  ```shell # The "race" argument is important.-valgrind --leak-check=yes $ZEOLITE_PATH/tests/leak-check/LeakTest race+$ZEOLITE_PATH/tests/leak-check/LeakTest race ```++*Do not use `valgrind` to run in `race` mode!* The latency introduced by+tracking memory usage will eliminate the race conditions that this mode is+intended to introduce, defeating the purpose of the test.  You should see `no race conditions this time` upon success. Any sort of error message means a crash, and thus a test failure.
tests/regressions.0rt view
@@ -292,3 +292,24 @@     return "return"   } }+++testcase "Issue #185 is fixed" {+  // https://github.com/ta0kira/zeolite/issues/185+  crash+  require "message"+}++concrete Type {+  @type sideEffects () -> (Bool)+}++define Type {+  sideEffects () {+    fail("message")+  }+}++unittest test {+  _ <- Type.sideEffects()+}
zeolite-lang.cabal view
@@ -1,7 +1,7 @@ cabal-version:       2.2  name:                zeolite-lang-version:             0.18.0.1+version:             0.18.1.0 synopsis:            Zeolite is a statically-typed, general-purpose programming language.  description: