/* *********************************************************************
This source file is a part of the standard library of Scol
For the latest info, see http://www.scolring.org
Copyright (c) 2013 Stephane Bisaro aka Iri.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt
********************************************************************* */
/*
* Standard functions for Scol
* See http://redmine.scolring.org/projects/tutorials/wiki/Scol_usage
* for more informations
*/
/*! \file stdlib.pkg
* \author Scol team
* \version 0.1
* \copyright GNU Lesser General Public License 2.0 or later
* \brief Scol Standard Library API
*
**/
/* prototype : used function from another package */
//proto std_fCmp = fun [F F] I;;
/* Set some prototypes to avoid some errors of compilation
(inappropriate given types) or logical programming errors */
proto std_cmpI = fun [I I] I;;
proto std_ncmpI = fun [I I] I;;
proto std_tupleCmp = fun [u0 u0 fun [u1 u1] I] I;;
proto std_objIsEqual = fun [u0 u0] I;;
proto std_clampT = fun [I u0 I] I;;
proto std_vectorIsEqual = fun [[I I I] [I I I]] I;;
/*! \brief Get if an Scol object is nil
*
* \ingroup std_lib
* Prototype : fun [u0] I
*
* \param u0 : any Scol object
* \return I : 1 if object is nil
**/
fun std_objIsNil (obj)=
obj == nil;;
/*! \brief Returns if two Scol objects are equal
*
* \ingroup std_lib
* Prototype : fun [u0 u0] I
*
* \param u0 : any Scol object
* \param u0 : another Scol object
* \return I : 1 if objects are equals
* \remark : It could be useful by calling from an other function, to compare two elements.
**/
fun std_objIsEqual (obj1, obj2)=
obj1 == obj2;;
/*! \brief Returns if two integers are equals or not
*
* \ingroup std_lib
* Prototype : fun [I I] I
*
* \param I : any integer
* \param I : another integer
* \return I : 1 if integers are equals
* \remark : It could be useful by calling from an other function, to compare two elements.
**/
fun std_cmpI (a, b)=
a == b;;
/*! \brief Returns if two float numbers are equals or not
*
* \ingroup std_lib
* Prototype : fun [F F] I
*
* \param F : any float number
* \param F : another float number
* \return I : 1 if float numbers are equals
* \remark : It could be useful by calling from an other function, to compare two elements.
* \warning This function has been removed. See std_fCmp in float.pkg
**/
/*fun std_cmpF (f, g)=
std_fCmp f g;;*/
/*! \brief Returns if two string are equals or not- Case-sensitive.
*
* \ingroup std_lib
* Prototype : fun [S S] I
*
* \param S : any string
* \param S : another string
* \return I : 1 if string are equals
* \remark : It could be useful by calling from an other function, to compare two elements.
**/
fun std_cmpS (s, t)=
!strcmp s t;;
/*! \brief Returns if two string are equals. Case-insensitive.
*
* \ingroup std_lib
* Prototype : fun [S S] I
*
* \param S : any string
* \param S : another string
* \return I : 1 if strings are equals
* \remark : It could be useful by calling from an other function, to compare two elements.
**/
fun std_cmpSi (s, t)=
!strcmpi s t;;
/*! \brief Returns if two integers are not equals
*
* \ingroup std_lib
* Prototype : fun [I I] I
*
* \param I : any integer
* \param I : another integer
* \return I : 1 if integers are not equals
* \remark : It could be useful by calling from an other function, to compare two elements.
**/
fun std_ncmpI (a, b)=
a != b;;
/*! \brief Returns if two float numbers are not equals
*
* \ingroup std_lib
* Prototype : fun [F F] I
*
* \param F : any float number
* \param F : another float number
* \return I : 1 if float numbers are not equals
* \remark : It could be useful by calling from an other function, to compare two elements.
*
* \warning This function has been removed. See std_fCmp in float.pkg
**/
/*fun std_ncmpF (f, g)=
!std_fCmp f g;;*/
/*! \brief Returns if two string are not equals. Case-sensitive.
*
* \ingroup std_lib
* Prototype : fun [S S] I
*
* \param S : any string
* \param S : another string
* \return I : 1 if strings are not equals
* \remark : It could be useful by calling from an other function, to compare two elements.
**/
fun std_ncmpS (s, t)=
if !strcmp s t then 0 else 1;;
/*! \brief Returns if two string are not equals. Case-insensitive.
*
* \ingroup std_lib
* Prototype : fun [S S] I
*
* \param S : any string
* \param S : another string
* \return I : 1 if strings are not equals
* \remark : It could be useful by calling from an other function, to compare two elements.
**/
fun std_ncmpSi (s, t)=
if !strcmpi s t then 0 else 1;;
/*! \brief Perform an entire division.
*
* \ingroup std_lib
* Prototype : fun [I I] I
*
* \param I : a
* \param I : b (if is equal to 0, the result will be nil)
* \return I : the integral quotient or nil if b = 0
**/
fun std_divide (a, b)=
if (b == 0) || (a == nil) || (b == nil) then
nil
else
a / b;;
/*! \brief Return some infos about the operating system. See 'osInfos'.
*
* \ingroup std_lib
* Prototype : fun [] S
*
* \return S : a formatted string
**/
fun std_os ()=
sprintf "%s\n%s\n%s\n%s\n" osInfos;;
/*! \brief Return some infos about the operating system. See 'memoryInfos'
* for more informations about the memory.
*
* \ingroup std_lib
* Prototype : fun [] [I I I]
*
* \return [I I I] :
* - the approximate percentage of physical memory that is in use
* - the amount of actual physical memory
* - the amount of physical memory currently available
**/
fun std_memory ()=
let memoryInfos -> [a b c _ _ _ _ _] in
[a b c];;
/*! \brief Perform a pause
*
* \ingroup std_lib
*
* Prototype : fun [I] I
*
* \param I : the number of second
* \return I : the "real" pause done, in milliseconds.
**/
fun std_sleep (second)=
let second*1000 -> ms in
let _tickcount -> start in
let start -> n in
(
while ms >= n-start do
set n = _tickcount;
n-start
);;
/*! \brief Return a random integer
*
* \ingroup std_lib
*
* Prototype : fun [I] I
*
* \param I : the maximum, the number will be between 0 and this maximum (it should
* not be greater than 32767).
* \return I : a random integer
**/
fun std_random (max)=
srand time;
mod rand max;;
fun std_starterscriptparse (list)=
let nil -> pkgs in
let nil -> funs in
(
while list != nil do
let strfind "_load \"" hd list 0 -> pos in
let strfind "\"" hd list pos+7 -> pos2 in
(
if pos != nil then
(
set pkgs = (strtrim substr hd list pos+7 pos2-pos-7) :: pkgs;
nil
)
else
let strfind "#" hd list 0 -> pos in
let strextr if pos == nil then strtrim hd list else strtrim substr hd list 0 pos -> words in
if words != nil then
set funs = [hd hd words tl hd words] :: funs
else
nil;
set list = tl list
);
[pkgs funs]
);;
/*! \brief Parse the launcher script of the current application
*
* \ingroup std_lib
*
* Prototype : fun [] [[S r1] [[S [S r1]] r1]]
*
* \return [[S r1] [[S [S r1]] r1]] : a tuple :
* - [S r1] : the list of packages
* - [[S [S r1]] r1] : a list of tuples. For each tuple :
* -# S : a function name (called from the launcher), such as "main"
* -# [S r1] : a list of its arguments
**/
fun std_starterScriptParse ()=
std_starterscriptparse lineextr _starterScript;; // _getpack _checkpack "tests/lib/lib.scol";;
/*! \brief Parse a launcher script
*
* \ingroup std_lib
*
* Prototype : fun [P] [[S r1] [[S [S r1]] r1]]
*
* \param P : a script read reference file
*
* \return [[S r1] [[S [S r1]] r1]] : a tuple (or nil if error) :
* - [S r1] : the list of packages
* - [[S [S r1]] r1] : a list of tuples. For each tuple :
* -# S : a function name (called from the launcher), such as "main"
* -# [S r1] : a list of its arguments
**/
fun std_starterScriptParseP (pFile)=
if pFile == nil then nil
else std_starterscriptparse lineextr _getpack pFile;;
fun std_getloadedpackages (env)=
if env == nil then
nil
else
(_envfirstname env) :: std_getloadedpackages _removepkg env;;
/*! \brief Returns the list of all loaded packages in a given channel.
*
* \ingroup std_lib
* Prototype : fun [Chn] [S r1]
*
* \param Chn : a channel, like _channel
*
* \return [S r1] : a list of all loaded packages in the channel or nil if an error occurs
**/
fun std_getLoadedPackages (chn)=
let _envchannel chn -> env in
std_getloadedpackages env;;
fun std_tuplesortcmp (a, b, flag)=
if flag then
a > b
else
a < b;;
fun std_tuplesortcmpf (a, b, flag)=
if flag then
a >. b
else
a <. b;;
fun std_tuplesort (tuple, f, flag)=
let tupleSize tuple -> iSize in
let 1 -> i in
while i < iSize do
let tupleGet tuple i nil -> a in
let i -> j in
(
// while (j > 0) && (std_tuplesortcmp a tupleGet tuple j-1 nil flag) do
while (j > 0) && (exec f with [a tupleGet tuple j-1 nil flag]) do
(
set tuple = tupleSet tuple j tupleGet tuple j-1 nil;
set j = j-1
);
set tuple = tupleSet tuple j a;
set i = i+1;
);
tuple;;
/*! \brief Sort the values of an integer tuple.
*
* \warning If the values are not integers, the result can be undefined.
*
* \ingroup std_lib
*
* Prototype: fun [u0] u0
*
* \param u0 : a tuple of integers
* \return u0 : the sorted tuple
**/
fun std_tupleSort (tuple)=
std_tuplesort tuple @std_tuplesortcmp 0;;
/*! \brief Sort the values of an integer tuple (reverse).
*
* \warning If the values are not integers, the result can be undefined.
*
* \ingroup std_lib
*
* Prototype: fun [u0] u0
*
* \param u0 : a tuple of integers
* \return u0 : the sorted tuple
**/
fun std_tupleSortR (tuple)=
std_tuplesort tuple @std_tuplesortcmp 1;;
/*! \brief Sort the values of a float tuple.
*
* \warning If the values are not float, the result can be undefined.
*
* \ingroup std_lib
*
* Prototype: fun [u0] u0
*
* \param u0 : a tuple of float numbers
* \return u0 : the sorted tuple
**/
fun std_tupleSortF (tuple)=
std_tuplesort tuple @std_tuplesortcmpf 0;;
/*! \brief Sort the values of a float tuple (reverse).
*
* \warning If the values are not float, the result can be undefined.
*
* \ingroup std_lib
*
* Prototype: fun [u0] u0
*
* \param u0 : a tuple of float numbers
* \return u0 : the sorted tuple
**/
fun std_tupleSortFR (tuple)=
std_tuplesort tuple @std_tuplesortcmpf 1;;
/*! \brief Clamp a value between two values
*
* \ingroup std_lib
*
* Prototype: fun [I I I] I
*
* \param I : an integer to clamp
* \param I : the minimum
* \param I : the maximum (if it is lesser than the minimum, the function will return nil)
*
* \return I : the clamped value or nil if error
* \see std_fClamp
**/
fun std_clamp (v, m, M)=
if m > M then nil else if v < m then m else if v > M then M else v;;
/*! \brief Clamp a value to a tuple
*
* \ingroup std_lib
*
* Prototype: fun [I u0 I] I
*
* \param I : an integer to clamp
* \param u0 : a tuple
* \param I : a default value to set if not found in the tuple
*
* \return I : the clamped value or nil if error
* \remark this function works too with the float numbers (value, tuple and default)
**/
fun std_clampT (v, tuple, default)=
if std_objIsNil tuple then
nil
else
let tupleSize tuple -> iSize in
let 0 -> res in
let 0 -> i in
(
while (i < iSize) && (!res) do
let tupleGet tuple i nil -> a in
if a == v then
set res = 1
else
set i = i+1;
if res then v else default
);;
fun std_clampenum (v, tuple, f)=
if std_objIsNil tuple then
nil
else
let tupleSize tuple -> iSize in
let tupleGet tuple 0 nil -> a in
let tupleGet tuple iSize-1 nil -> b in
let exec f with [a v 1] -> r in
if r then
a
else
let exec f with [v b 1] -> r in
if r then
b
else
v;;
/*! \brief Clamp an integer like an enum. The tuple should be
* sorted : only the first and the last element are compared.
*
* \ingroup std_lib
*
* Prototype: fun [I u0] I
*
* \param I : an integer to clamp
* \param u0 : any integer tuple
*
* \return I : the clamped value or nil if error
**/
fun std_enumClamp (v, tuple)=
std_clampenum v tuple @std_tuplesortcmp;;
/*! \brief Clamp a float number like an enum. The tuple should be
* sorted : only the first and the last element are compared.
*
* \ingroup std_lib
*
* Prototype: fun [F u0] F
*
* \param F : a float to clamp
* \param u0 : any float tuple
*
* \return F : the clamped value or nil if error
**/
fun std_enumClampF (v, tuple)=
std_clampenum v tuple @std_tuplesortcmpf;;
/*! \brief Return the size of a tuple
*
* \ingroup std_lib
*
* Prototype: fun [u0] I
*
* \param u0 : any tuple
*
* \return I : the size or nil if error
**/
fun std_tupleSize (tuple)=
if std_objIsNil tuple then
nil
else
tupleSize tuple;;
/*! \brief Compare two tuples
*
* \ingroup std_lib
*
* Prototype: fun [u0 u0 fun [u0 u0] I] I
*
* \param u0 : any tuple
* \param u0 : another tuple
* \param fun [u0 u0] I : function called to compare two elements.
* It should return 1 if these two elements are equals.
*
* \return I : 1 if equals, else 0
* \remark the two tuples must have the same type, otherwise an error
* will occur during the compilation.
**/
fun std_tupleCmp (tuple1, tuple2, fCmp)=
if (std_objIsNil tuple1) && (std_objIsNil tuple2) then
1
else if (std_objIsNil tuple1) || (std_objIsNil tuple2) then
0
else
/* With prototype in the head of this file,
the two types are the same type, so they are the same size.
Thus, it is useless to compare their size ! */
/*let std_tupleSize tuple1 -> size1 in
let std_tupleSize tuple2 -> size2 in
if size1 != size2 then
0
else*/
let std_tupleSize tuple1 -> size1 in
let 1 -> res in
let 0 -> i in
(
while (i < size1) && (res) do
let tupleGet tuple1 i nil -> t1 in
let tupleGet tuple2 i nil -> t2 in
if exec fCmp with [t1 t2] then
set i = i+1
else
set res = 0;
res
);;
/*! \brief Return if a value is found in a tuple.
*
* \ingroup std_lib
*
* Prototype: fun [u0 u1] I
*
* \param u0 : any tuple
* \param u1 : a value
*
* \return I : 1 if found, 0 if not found or nil if error
* \see std_tupleIsFoundS
* \see std_tupleIsFoundSi
**/
fun std_tupleIsFound (tuple, v)=
if std_objIsNil tuple then
nil
else
let tupleSize tuple -> iSize in
let 0 -> res in
let 0 -> i in
(
while (i < iSize) && (!res) do
if v == tupleGet tuple i nil then
set res = 1
else
set i = i+1;
res
);;
fun std_tupleisfounds (tuple, s, isSensitive)=
let tupleSize tuple -> iSize in
let 0 -> res in
let 0 -> i in
(
while (i < iSize) && (!res) do
if isSensitive then
if !strcmp s tupleGet tuple i nil then
set res = 1
else
set i = i+1
else
if !strcmpi s tupleGet tuple i nil then
set res = 1
else
set i = i+1;
res
);;
/*! \brief Return if a string is found in a tuple. Case sensitive.
*
* \ingroup std_lib
*
* Prototype: fun [u0 S] I
*
* \param u0 : any string tuple
* \param u1 : a value
*
* \return I : 1 if found, 0 if not found or nil if error
* \see std_tupleIsFound
* \see std_tupleIsFoundSi
**/
fun std_tupleIsFoundS (tuple, s)=
std_tupleisfounds tuple s 1;;
/*! \brief Return if a string is found in a tuple. Case insensitive.
*
* \ingroup std_lib
*
* Prototype: fun [u0 S] I
*
* \param u0 : any tuple
* \param u1 : a value
*
* \return I : 1 if found, 0 if not found or nil if error
* \see std_tupleIsFound
* \see std_tupleIsFoundS
**/
fun std_tupleIsFoundSi (tuple, s)=
std_tupleisfounds tuple s 0;;
/*! \brief Create a tuple.
*
* \ingroup std_lib
*
* Prototype: fun [I [u0 r1] u1] u1
*
* \param I : the size of the new tuple (1 or +)
* \param [u0 r1] : a list to set the tuple elements. Initially,
* each element is set to nil, this list is a convenience to set another
* values. If the list is bigger than the size, its last elements will be
* ignored. If it is smaller than the size, another elements will keep
* at nil.
* \param u1 : should be always nil.
*
* \return u1 : the new tuple or nil if error
**/
fun std_tupleNew (size, values, tuple)=
if (size == nil) || (size < 1) then
nil
else
if values == nil then
set tuple = tupleNew size nil nil
else
(
set tuple = tupleNew size nil nil;
let 0 -> i in
while (i < size) && (values != nil) do
(
set tuple = tupleSet tuple i hd values;
set values = tl values;
set i = i+1;
);
tuple
);;
/*! \brief Return if a tuple is nil or each item is nil
*
* \ingroup std_lib
*
* Prototype: fun [u0] I
*
* \param u0 : any tuple
*
* \return I : 1 if nil else 0
**/
fun std_tupleIsNil (tuple)=
if std_objIsNil tuple then
1
else
let tupleSize tuple -> iSize in
let 0 -> i in
let 1 -> res in
(
while (i < iSize) && (res) do
if std_objIsNil tupleGet tuple i nil then
set i = i+1
else
set res = 0;
res
);;
/*! \brief Return if a tuple has an (or more) item at nil
*
* \ingroup std_lib
*
* Prototype: fun [u0] I
*
* \param u0 : any tuple
*
* \return I : 1 if yes else 0
**/
fun std_tupleHasNil (tuple)=
if std_objIsNil tuple then
1
else
let tupleSize tuple -> iSize in
let 0 -> i in
let 0 -> res in
(
while (i < iSize) && (!res) do
if std_objIsNil tupleGet tuple i nil then
set res = 1
else
set i = i+1;
res
);;
/*! \brief Return if a vector is null or not
*
* \ingroup std_lib
*
* Prototype: fun [[I I I]] I
*
* \param [I I I] : integer vector
*
* \return I : 1 if equal at 0 else 0
**/
fun std_vectorIsNullI (v)=
let v -> [x y z] in
(x == 0) && (y == 0) && (z == 0);;
/*!
* \brief Return if a vector is null or not
*
* \ingroup std_lib
*
*
* Prototype: fun [[F F F]] I
*
* \param [F F F] : float vector
*
* \return I : 1 if equal at 0 else 0
**/
fun std_vectorIsNullF (v)=
let v -> [x y z] in
(x == 0.0) && (y == 0.0) && (z == 0.0);;
/*! \brief Return if a vector is "" or not
*
* \ingroup std_lib
*
*
* Prototype: fun [[S S S]] I
*
* \param [S S S] : string vector
*
* \return I : 1 yes 1 no 0
**/
fun std_vectorIsNullS (v)=
let v -> [x y z] in
(!strcmp x "") && (!strcmp y "") && (!strcmp z "");;
/*! \brief Return if a vector is nil or not
*
* \ingroup std_lib
*
*
* Prototype: fun [[u0 u1 u2]] I
*
* \param [u0 u1 u2] : a vector
*
* \return I : 1 if equal at nil else 0
**/
fun std_vectorIsNil (v)=
let v -> [x y z] in
(x == nil) && (y == nil) && (z == nil);;
/*! \brief Return if two integer vectors are equals
*
* \ingroup std_lib
*
*
* Prototype: fun [[I I I] [I I I]] I
*
* \param [I I I] : first integer vector
* \param [I I I] : second integer vector
*
* \return I : 1 if are equuals else 0
*
* \see std_vectorIsEqualF in lib/std/float.pkg with floating number.
**/
fun std_vectorIsEqual (v1, v2)=
let v1 -> [x1 y1 z1] in
let v2 -> [x2 y2 z2] in
(x1 == x2) && (y1 == y2) && (z1 == z2);;
/*! \brief Return if two string vectors are equals. Case-sensitive.
*
* \ingroup std_lib
*
*
* Prototype: fun [[S S S] [S S S]] I
*
* \param [S S S] : first string vector
* \param [S S S] : second string vector
*
* \return I : 1 if are equuals else 0
**/
fun std_vectorIsEqualS (v1, v2)=
let v1 -> [x1 y1 z1] in
let v2 -> [x2 y2 z2] in
(!strcmp x1 x2) && (!strcmp y1 y2) && (!strcmp z1 z2);;
/*! \brief Return if two string vectors are equals. Case-insensitive.
*
* \ingroup std_lib
*
*
* Prototype: fun [[S S S] [S S S]] I
*
* \param [S S S] : first string vector
* \param [S S S] : second string vector
*
* \return I : 1 if are equuals else 0
**/
fun std_vectorIsEqualSi (v1, v2)=
let v1 -> [x1 y1 z1] in
let v2 -> [x2 y2 z2] in
(!strcmpi x1 x2) && (!strcmpi y1 y2) && (!strcmpi z1 z2);;
/*! \brief Return if two vectors are equals
*
* \ingroup std_lib
*
*
* Prototype: fun [[u0 u1 u2] [u0 u1 u2]] I
*
* \param [u0 u1 u2] : first vector
* \param [u0 u1 u2] : second vector
*
* \return I : 1 if are equuals else 0
* \remark You should use the specific comparaison vectors function if
* the elements are I, F or S.
**/
fun std_vectorIsEqualAny (v1, v2)=
std_vectorIsEqual v1 v2;;
/*! \brief Add two vectors (integer)
*
* \ingroup std_lib
*
*
* Prototype: fun [[I I I] [I I I]] [I I I]
*
* \param [I I I] : first integer vector
* \param [I I I] : second integer vector
*
* \return [I I I] : vector result
**/
fun std_vectorAddI (iV1, iV2)=
let iV1 -> [iX1 iY1 iZ1] in
let iV2 -> [iX2 iY2 iZ2] in
[add iX1 iX2 add iY1 iY2 add iZ1 iZ2];;
/*! \brief Add two vectors (float number)
*
* \ingroup std_lib
*
*
* Prototype: fun [[F F F] [F F F]] [F F F]
*
* \param [F F F] : first float vector
* \param [F F F] : second float vector
*
* \return [F F F] : vector result
**/
fun std_vectorAddF (fV1, fV2)=
let fV1 -> [fX1 fY1 fZ1] in
let fV2 -> [fX2 fY2 fZ2] in
[addf fX1 fX2 addf fY1 fY2 addf fZ1 fZ2];;
/*! \brief Add two vectors (string element)
*
* \ingroup std_lib
*
*
* Prototype: fun [[S S S] [S S S]] [S S S]
*
* \param [S S S] : first string vector
* \param [S S S] : second string vector
*
* \return [S S S] : vector result
**/
fun std_vectorAddS (szV1, szV2)=
let szV1 -> [szX1 szY1 szZ1] in
let szV2 -> [szX2 szY2 szZ2] in
[strcat szX1 szX2 strcat szY1 szY2 strcat szZ1 szZ2];;
/*! \brief Sub two vectors (integer)
*
* \ingroup std_lib
*
*
* Prototype: fun [[I I I] [I I I]] [I I I]
*
* \param [I I I] : first integer vector
* \param [I I I] : second integer vector
*
* \return [I I I] : vector result
**/
fun std_vectorSubI (iV1, iV2)=
let iV1 -> [iX1 iY1 iZ1] in
let iV2 -> [iX2 iY2 iZ2] in
[sub iX1 iX2 sub iY1 iY2 sub iZ1 iZ2];;
/*! \brief Sub two vectors (float number)
*
* \ingroup std_lib
*
*
* Prototype: fun [[F F F] [F F F]] [F F F]
*
* \param [F F F] : first float vector
* \param [F F F] : second float vector
*
* \return [F F F] : vector result
**/
fun std_vectorSubF (fV1, fV2)=
let fV1 -> [fX1 fY1 fZ1] in
let fV2 -> [fX2 fY2 fZ2] in
[subf fX1 fX2 subf fY1 fY2 subf fZ1 fZ2];;
/*! \brief multiply two vectors (integer)
*
* \ingroup std_lib
*
*
* Prototype: fun [[I I I] [I I I]] [I I I]
*
* \param [I I I] : first integer vector
* \param [I I I] : second integer vector
*
* \return [I I I] : vector result
**/
fun std_vectorMultiplyI (iV1, iV2)=
let iV1 -> [iX1 iY1 iZ1] in
let iV2 -> [iX2 iY2 iZ2] in
[mul iX1 iX2 mul iY1 iY2 mul iZ1 iZ2];;
/*! \brief Multiply two vectors (float number)
*
* \ingroup std_lib
*
*
* Prototype: fun [[F F F] [F F F]] [F F F]
*
* \param [F F F] : first float vector
* \param [F F F] : second float vector
*
* \return [F F F] : vector result
**/
fun std_vectorMultiplyF (fV1, fV2)=
let fV1 -> [fX1 fY1 fZ1] in
let fV2 -> [fX2 fY2 fZ2] in
[mulf fX1 fX2 mulf fY1 fY2 mulf fZ1 fZ2];;
/*! \brief Divide two vectors (integer)
*
* \ingroup std_lib
*
*
* Prototype: fun [[I I I] [I I I]] [I I I]
*
* \param [I I I] : first integer vector
* \param [I I I] : second integer vector
*
* \return [I I I] : vector result
**/
fun std_vectorDivideI (iV1, iV2)=
if std_vectorIsNullI iV2 then
nil
else
let iV1 -> [iX1 iY1 iZ1] in
let iV2 -> [iX2 iY2 iZ2] in
[div iX1 iX2 div iY1 iY2 div iZ1 iZ2];;
/*! \brief Divide two vectors (float number)
*
* \ingroup std_lib
*
*
* Prototype: fun [[F F F] [F F F]] [F F F]
*
* \param [F F F] : first float vector
* \param [F F F] : second float vector
*
* \return [F F F] : vector result
**/
fun std_vectorDivideF (fV1, fV2)=
if std_vectorIsNullF fV2 then
nil
else
let fV1 -> [fX1 fY1 fZ1] in
let fV2 -> [fX2 fY2 fZ2] in
[divf fX1 fX2 divf fY1 fY2 divf fZ1 fZ2];;
/*! \brief Create a vector in duplicating a same given value
*
* \ingroup std_lib
*
*
* Prototype: fun [u0] [u0 u0 u0]
*
* \param u0 : any value
*
* \return [u0 u0 u0] : vector result
**/
fun std_vectorSet (v)=
[v v v];;
/*! \brief Check if a flag is in a flags combination, like 'WN_MENU|WN_SIZEBOX|WN_MINBOX'
*
* \ingroup std_lib
* Prototype : fun [I I] I
*
* \param I : a flags combination
* \param I : a flag to check
* \return I : 1 if present else 0
**/
fun std_isFlagPresent (flags, flag)=
if flags & flag then 1 else 0;;
/*! \brief Remove a flag in a flags combination, like 'WN_MENU|WN_SIZEBOX|WN_MINBOX'
*
* \ingroup std_lib
* Prototype : fun [I I] I
*
* \param I : a flags combination
* \param I : a flag to remove
* \return I : a new combination
**/
fun std_removeFlag (flags, flag)=
flags & (~flag);;
/*! \brief Add a flag in a flags combination, like 'WN_MENU|WN_SIZEBOX|WN_MINBOX'
*
* \ingroup std_lib
* Prototype : fun [I I] I
*
* \param I : a flags combination
* \param I : a flag to add
* \return I : a new combination
**/
fun std_addFlag (flags, flag)=
if std_isFlagPresent flags flag then // useful ?
flags | flag
else
flags;;
proto std_sameType = fun [u0 u0] I;;
/*! \brief Check if two objects have the same type.
*
* This function should be NEVER used in production !
*
* In development or debug mode, this function causes a runtime error
* if the two objects have a different type.
*
* \ingroup std_lib
* Prototype : fun [u0 u0] I
*
* \param u0 : any object
* \param u0 : any object
* \return I : always 0
**/
fun std_sameType (o1, o2)= 0;;
/*! \brief ... */
fun std_addFifo (x, f)=
let x :: nil -> l in
if f == nil then
[l l]
else
let f->[a b] in
(
mutate b<-[_ l];
[a l]
);;
/*! \brief ... */
fun std_getFifo (f)=
if f == nil then
[nil nil]
else
let f -> [a b] in
if a == b then
[hd a nil]
else
[hd a [tl a b]];;
/*! \brief ... */
fun std_sizeFifo (f)=
if f == nil then
0
else
let f -> [a _] in
sizelist a;;
/*! \brief ... */
fun std_concFifo (f, g)=
if f == nil then
g
else if g == nil then
f
else
let f -> [a b] in
let g -> [c d] in
(
mutate b <- [_ c];
[a d]
);;
/*! \brief Create a new unplugged channel with the minimal
* environment.
*
* \ingroup std_lib
* Prototype : fun [S] Chn
*
* \param S : a script to execute immediately in the new channel.
* \return Chn : the new channel or nil if error (unable to create the new channel)
* \remark Don't use this function at this time !
**/
fun std_newUnChn (szScript)=
_openchannel nil szScript nil;;
/*! \brief Create a new unplugged channel with the current
* environment.
*
* \ingroup std_lib
* Prototype : fun [S] Chn
*
* \param S : a script to execute immediately in the new channel.
* \return Chn : the new channel or nil if error (unable to create the new channel)
* \remark Don't use this function at this time !
**/
fun std_newUnCurChn (szScript)=
_openchannel nil szScript _envchannel _channel;;
/*! \brief Create a new unplugged channel with the current
* environment.
*
* \ingroup std_lib
* Prototype : fun [S S S] Chn
*
* \param S : a script to execute immediately in the new channel.
* \param S : the function name to call when a connection is received.
* \param S : the function name to call when a connection is closed.
* \return Chn : the new channel or nil if error (unable to create the new channel)
* \remark These two functions must be known in the new channel environnement.
*
* \remark Don't use this function at this time !
**/
fun std_newUnCurChnEx (szScript, funCon, funClo)=
let sprintf "fun _connected ()=exec @%s with [];;\nfun _closed ()=exec @%s with [];;\n\n%s" [funCon funClo szScript] -> szScriptUpt in
_openchannel nil szScriptUpt nil;;
/*! \brief Create a new unplugged channel with the minimal
* environment.
*
* \ingroup std_lib
* Prototype : fun [S S S] Chn
*
* \param S : a script to execute immediately in the new channel.
* \param S : the function name to call when a connection is received.
* \param S : the function name to call when a connection is closed.
* \return Chn : the new channel or nil if error (unable to create the new channel)
* \remark These two functions must be known in the new channel environnement.
*
* \remark Don't use this function at this time !
* \see std_newUnChnExP
**/
fun std_newUnChnEx (szScript, funCon, funClo)=
let sprintf "%s\n_loadS \"fun _connected ()=%s;;\nfun _closed ()=%s;;\"\nmain"
[szScript funCon funClo]
-> szScriptUpt in
let _fooS szScriptUpt -> _ in
_openchannel nil szScriptUpt nil;;
/*! \brief Create a new unplugged channel with the minimal
* environment.
*
* \ingroup std_lib
* Prototype : fun [[S r1] S S] Chn
*
* \param [S r1] : a list of files to load immediately in the new channel.
* \param S : the function name to call when a connection is received.
* \param S : the function name to call when a connection is closed.
* \return Chn : the new channel or nil if error (unable to create the new channel)
* \remark These two functions must be known in the new channel environnement.
* \remark Don't use this function at this time !
**/
fun std_newUnChnExP (pFiles, funCon, funClo)=
let "_loadS \"" -> szScript in
let 0 -> res in
(
while (pFiles != nil) do
let _checkpack hd pFiles -> pFile in
if pFile == nil then
(
set pFiles = nil;
set res = 1;
)
else
(
set szScript = sprintf "%s%s\n" [szScript _getpack pFile];
set pFiles = tl pFiles;
0
);
if (!res) then
(
set szScript = sprintf "%sfun _connected ()=%s;;\nfun _closed ()=%s;;%s" [szScript funCon funClo "\""];
_openchannel nil szScript nil
)
else
nil;
);;