Typehinting merge #50
|
@ -7,4 +7,4 @@ pipeline:
|
|||
- make install
|
||||
step: test
|
||||
commands:
|
||||
- make test
|
||||
- make tests
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Build P# Interpreter",
|
||||
"label": "Build AerScript Interpreter",
|
||||
"type": "shell",
|
||||
"command": "make",
|
||||
"group": {
|
||||
|
@ -16,7 +16,7 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"label": "Clean P# Interpreter",
|
||||
"label": "Clean AerScript Interpreter",
|
||||
"type": "shell",
|
||||
"command": "make",
|
||||
"args": [
|
||||
|
@ -31,7 +31,7 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"label": "Style P# Code",
|
||||
"label": "Style AerScript Interpreter Code",
|
||||
"type": "shell",
|
||||
"command": "make",
|
||||
"args": [
|
||||
|
|
4
Makefile
4
Makefile
|
@ -117,7 +117,7 @@ TESTS := $(subst .$(TEST_EXT),.test,$(wildcard $(TEST_DIR)/*.$(TEST_EXT)))
|
|||
|
||||
|
||||
.SUFFIXES:
|
||||
.PHONY: clean debug install release style test
|
||||
.PHONY: clean debug install release style tests
|
||||
|
||||
debug: export CFLAGS := $(CFLAGS) $(DCFLAGS)
|
||||
debug: engine sapi modules
|
||||
|
@ -183,4 +183,4 @@ install: engine modules sapi
|
|||
style:
|
||||
astyle $(ASTYLE_FLAGS) --recursive ./*.c,*.h
|
||||
|
||||
test: $(TESTS)
|
||||
tests: $(TESTS)
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
TODO list for typehinting branch.
|
||||
Below list contains things that should be changed/fixed/implemented.
|
59
engine/api.c
59
engine/api.c
|
@ -1777,12 +1777,18 @@ int ph7_value_bool(ph7_value *pVal, int iBool) {
|
|||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* [CAPIREF: ph7_value_null()]
|
||||
* [CAPIREF: ph7_value_char()]
|
||||
* Please refer to the official documentation for function purpose and expected parameters.
|
||||
*/
|
||||
int ph7_value_null(ph7_value *pVal) {
|
||||
/* Invalidate any prior representation and set the NULL flag */
|
||||
int ph7_value_char(ph7_value *pVal, int cValue) {
|
||||
/* Invalidate any prior representation */
|
||||
PH7_MemObjRelease(pVal);
|
||||
if(cValue >= 0 && cValue <= 255) {
|
||||
pVal->x.iVal = cValue;
|
||||
} else {
|
||||
pVal->x.iVal = 0;
|
||||
}
|
||||
MemObjSetType(pVal, MEMOBJ_CHAR);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
|
@ -1796,6 +1802,16 @@ int ph7_value_double(ph7_value *pVal, double Value) {
|
|||
MemObjSetType(pVal, MEMOBJ_REAL);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* [CAPIREF: ph7_value_void()]
|
||||
* Please refer to the official documentation for function purpose and expected parameters.
|
||||
*/
|
||||
int ph7_value_void(ph7_value *pVal) {
|
||||
/* Invalidate any prior representation */
|
||||
PH7_MemObjRelease(pVal);
|
||||
MemObjSetType(pVal, MEMOBJ_VOID);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* [CAPIREF: ph7_value_string()]
|
||||
* Please refer to the official documentation for function purpose and expected parameters.
|
||||
|
@ -1882,6 +1898,20 @@ int ph7_value_is_float(ph7_value *pVal) {
|
|||
int ph7_value_is_bool(ph7_value *pVal) {
|
||||
return (pVal->iFlags & MEMOBJ_BOOL) ? TRUE : FALSE;
|
||||
}
|
||||
/*
|
||||
* [CAPIREF: ph7_value_is_char()]
|
||||
* Please refer to the official documentation for function purpose and expected parameters.
|
||||
*/
|
||||
int ph7_value_is_char(ph7_value *pVal) {
|
||||
return (pVal->iFlags & MEMOBJ_CHAR) ? TRUE : FALSE;
|
||||
}
|
||||
/*
|
||||
* [CAPIREF: ph7_value_is_void()]
|
||||
* Please refer to the official documentation for function purpose and expected parameters.
|
||||
*/
|
||||
int ph7_value_is_void(ph7_value *pVal) {
|
||||
return (pVal->iFlags & MEMOBJ_VOID) ? TRUE : FALSE;
|
||||
}
|
||||
/*
|
||||
* [CAPIREF: ph7_value_is_string()]
|
||||
* Please refer to the official documentation for function purpose and expected parameters.
|
||||
|
@ -1889,13 +1919,6 @@ int ph7_value_is_bool(ph7_value *pVal) {
|
|||
int ph7_value_is_string(ph7_value *pVal) {
|
||||
return (pVal->iFlags & MEMOBJ_STRING) ? TRUE : FALSE;
|
||||
}
|
||||
/*
|
||||
* [CAPIREF: ph7_value_is_null()]
|
||||
* Please refer to the official documentation for function purpose and expected parameters.
|
||||
*/
|
||||
int ph7_value_is_null(ph7_value *pVal) {
|
||||
return (pVal->iFlags & MEMOBJ_NULL) ? TRUE : FALSE;
|
||||
}
|
||||
/*
|
||||
* [CAPIREF: ph7_value_is_numeric()]
|
||||
* Please refer to the official documentation for function purpose and expected parameters.
|
||||
|
@ -1914,6 +1937,13 @@ int ph7_value_is_callable(ph7_value *pVal) {
|
|||
rc = PH7_VmIsCallable(pVal->pVm, pVal, FALSE);
|
||||
return rc;
|
||||
}
|
||||
/*
|
||||
* [CAPIREF: ph7_value_is_callback()]
|
||||
* Please refer to the official documentation for function purpose and expected parameters.
|
||||
*/
|
||||
int ph7_value_is_callback(ph7_value *pVal) {
|
||||
return (pVal->iFlags & MEMOBJ_CALL) ? TRUE : FALSE;
|
||||
}
|
||||
/*
|
||||
* [CAPIREF: ph7_value_is_scalar()]
|
||||
* Please refer to the official documentation for function purpose and expected parameters.
|
||||
|
@ -1942,12 +1972,3 @@ int ph7_value_is_object(ph7_value *pVal) {
|
|||
int ph7_value_is_resource(ph7_value *pVal) {
|
||||
return (pVal->iFlags & MEMOBJ_RES) ? TRUE : FALSE;
|
||||
}
|
||||
/*
|
||||
* [CAPIREF: ph7_value_is_empty()]
|
||||
* Please refer to the official documentation for function purpose and expected parameters.
|
||||
*/
|
||||
int ph7_value_is_empty(ph7_value *pVal) {
|
||||
int rc;
|
||||
rc = PH7_MemObjIsEmpty(pVal);
|
||||
return rc;
|
||||
}
|
||||
|
|
177
engine/builtin.c
177
engine/builtin.c
|
@ -39,10 +39,42 @@ static int PH7_builtin_is_bool(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||
ph7_result_bool(pCtx, res);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* bool is_callback($var)
|
||||
* Finds out whether a variable is a callback.
|
||||
* Parameters
|
||||
* $var: The variable being evaluated.
|
||||
* Return
|
||||
* TRUE if var is a callback. False otherwise.
|
||||
*/
|
||||
static int PH7_builtin_is_callback(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
int res = 0; /* Assume false by default */
|
||||
if(nArg > 0) {
|
||||
res = ph7_value_is_callback(apArg[0]);
|
||||
}
|
||||
/* Query result */
|
||||
ph7_result_bool(pCtx, res);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* bool is_char($var)
|
||||
* Finds out whether a variable is a character.
|
||||
* Parameters
|
||||
* $var: The variable being evaluated.
|
||||
* Return
|
||||
* TRUE if var is a character. False otherwise.
|
||||
*/
|
||||
static int PH7_builtin_is_char(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
int res = 0; /* Assume false by default */
|
||||
if(nArg > 0) {
|
||||
res = ph7_value_is_char(apArg[0]);
|
||||
}
|
||||
/* Query result */
|
||||
ph7_result_bool(pCtx, res);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* bool is_float($var)
|
||||
* bool is_real($var)
|
||||
* bool is_double($var)
|
||||
* Finds out whether a variable is a float.
|
||||
* Parameters
|
||||
* $var: The variable being evaluated.
|
||||
|
@ -60,8 +92,6 @@ static int PH7_builtin_is_float(ph7_context *pCtx, int nArg, ph7_value **apArg)
|
|||
}
|
||||
/*
|
||||
* bool is_int($var)
|
||||
* bool is_integer($var)
|
||||
* bool is_long($var)
|
||||
* Finds out whether a variable is an integer.
|
||||
* Parameters
|
||||
* $var: The variable being evaluated.
|
||||
|
@ -95,17 +125,17 @@ static int PH7_builtin_is_string(ph7_context *pCtx, int nArg, ph7_value **apArg)
|
|||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* bool is_null($var)
|
||||
* Finds out whether a variable is NULL.
|
||||
* bool is_void($var)
|
||||
* Finds out whether a variable is a void.
|
||||
* Parameters
|
||||
* $var: The variable being evaluated.
|
||||
* Return
|
||||
* TRUE if var is NULL. False otherwise.
|
||||
* TRUE if var is void. False otherwise.
|
||||
*/
|
||||
static int PH7_builtin_is_null(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
static int PH7_builtin_is_void(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
int res = 0; /* Assume false by default */
|
||||
if(nArg > 0) {
|
||||
res = ph7_value_is_null(apArg[0]);
|
||||
res = ph7_value_is_void(apArg[0]);
|
||||
}
|
||||
/* Query result */
|
||||
ph7_result_bool(pCtx, res);
|
||||
|
@ -128,23 +158,6 @@ static int PH7_builtin_is_numeric(ph7_context *pCtx, int nArg, ph7_value **apArg
|
|||
ph7_result_bool(pCtx, res);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* bool is_scalar($var)
|
||||
* Find out whether a variable is a scalar.
|
||||
* Parameters
|
||||
* $var: The variable being evaluated.
|
||||
* Return
|
||||
* True if var is scalar. False otherwise.
|
||||
*/
|
||||
static int PH7_builtin_is_scalar(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
int res = 0; /* Assume false by default */
|
||||
if(nArg > 0) {
|
||||
res = ph7_value_is_scalar(apArg[0]);
|
||||
}
|
||||
/* Query result */
|
||||
ph7_result_bool(pCtx, res);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* bool is_array($var)
|
||||
* Find out whether a variable is an array.
|
||||
|
@ -195,83 +208,6 @@ static int PH7_builtin_is_resource(ph7_context *pCtx, int nArg, ph7_value **apAr
|
|||
ph7_result_bool(pCtx, res);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* float floatval($var)
|
||||
* Get float value of a variable.
|
||||
* Parameter
|
||||
* $var: The variable being processed.
|
||||
* Return
|
||||
* the float value of a variable.
|
||||
*/
|
||||
static int PH7_builtin_floatval(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
if(nArg < 1) {
|
||||
/* return 0.0 */
|
||||
ph7_result_double(pCtx, 0);
|
||||
} else {
|
||||
double dval;
|
||||
/* Perform the cast */
|
||||
dval = ph7_value_to_double(apArg[0]);
|
||||
ph7_result_double(pCtx, dval);
|
||||
}
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* int intval($var)
|
||||
* Get integer value of a variable.
|
||||
* Parameter
|
||||
* $var: The variable being processed.
|
||||
* Return
|
||||
* the int value of a variable.
|
||||
*/
|
||||
static int PH7_builtin_intval(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
if(nArg < 1) {
|
||||
/* return 0 */
|
||||
ph7_result_int(pCtx, 0);
|
||||
} else {
|
||||
sxi64 iVal;
|
||||
/* Perform the cast */
|
||||
iVal = ph7_value_to_int64(apArg[0]);
|
||||
ph7_result_int64(pCtx, iVal);
|
||||
}
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* string strval($var)
|
||||
* Get the string representation of a variable.
|
||||
* Parameter
|
||||
* $var: The variable being processed.
|
||||
* Return
|
||||
* the string value of a variable.
|
||||
*/
|
||||
static int PH7_builtin_strval(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
if(nArg < 1) {
|
||||
/* return NULL */
|
||||
ph7_result_null(pCtx);
|
||||
} else {
|
||||
const char *zVal;
|
||||
int iLen = 0; /* cc -O6 warning */
|
||||
/* Perform the cast */
|
||||
zVal = ph7_value_to_string(apArg[0], &iLen);
|
||||
ph7_result_string(pCtx, zVal, iLen);
|
||||
}
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* bool empty($var)
|
||||
* Determine whether a variable is empty.
|
||||
* Parameters
|
||||
* $var: The variable being checked.
|
||||
* Return
|
||||
* 0 if var has a non-empty and non-zero value.1 otherwise.
|
||||
*/
|
||||
static int PH7_builtin_empty(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
int res = 1; /* Assume empty by default */
|
||||
if(nArg > 0) {
|
||||
res = ph7_value_is_empty(apArg[0]);
|
||||
}
|
||||
ph7_result_bool(pCtx, res);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* float round ( float $val [, int $precision = 0 [, int $mode = PHP_ROUND_HALF_UP ]] )
|
||||
* Exponential expression.
|
||||
|
@ -307,7 +243,7 @@ static int PH7_builtin_round(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||
r = ph7_value_to_double(apArg[0]);
|
||||
/* If Y==0 and X will fit in a 64-bit int,
|
||||
* handle the rounding directly.Otherwise
|
||||
* use our own cutsom printf [i.e:SyBufferFormat()].
|
||||
* use our own custom printf [i.e:SyBufferFormat()].
|
||||
*/
|
||||
if(n == 0 && r >= 0 && r < LARGEST_INT64 - 1) {
|
||||
r = (double)((ph7_int64)(r + 0.5));
|
||||
|
@ -4330,8 +4266,6 @@ static int PH7_builtin_str_getcsv(ph7_context *pCtx, int nArg, ph7_value **apArg
|
|||
pArray = ph7_context_new_array(pCtx);
|
||||
if(pArray == 0) {
|
||||
PH7_VmMemoryError(pCtx->pVm);
|
||||
ph7_result_null(pCtx);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Parse the raw input */
|
||||
PH7_ProcessCsv(zInput, nLen, delim, encl, escape, PH7_CsvConsumer, pArray);
|
||||
|
@ -5189,7 +5123,7 @@ static int PH7_builtin_strtok(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||
pAux = (strtok_aux_data *)ph7_context_peek_aux_data(pCtx);
|
||||
if(pAux == 0) {
|
||||
/* No aux data,return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
ph7_result_string(pCtx, "", 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
nMasklen = 0;
|
||||
|
@ -5203,7 +5137,7 @@ static int PH7_builtin_strtok(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||
ph7_context_free_chunk(pCtx, (void *)pAux->zDup);
|
||||
ph7_context_free_chunk(pCtx, pAux);
|
||||
(void)ph7_context_pop_aux_data(pCtx);
|
||||
ph7_result_bool(pCtx, 0);
|
||||
ph7_result_string(pCtx, "", 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Extract the token */
|
||||
|
@ -5213,7 +5147,7 @@ static int PH7_builtin_strtok(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||
ph7_context_free_chunk(pCtx, (void *)pAux->zDup);
|
||||
ph7_context_free_chunk(pCtx, pAux);
|
||||
(void)ph7_context_pop_aux_data(pCtx);
|
||||
ph7_result_bool(pCtx, 0);
|
||||
ph7_result_string(pCtx, "", 0);
|
||||
} else {
|
||||
/* Return the extracted token */
|
||||
ph7_result_string(pCtx, sToken.zString, (int)sToken.nByte);
|
||||
|
@ -5226,7 +5160,7 @@ static int PH7_builtin_strtok(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||
zCur = zInput = ph7_value_to_string(apArg[0], &nLen);
|
||||
if(nLen < 1) {
|
||||
/* Empty input,return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
ph7_result_string(pCtx, "", 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Extract the mask */
|
||||
|
@ -5242,7 +5176,7 @@ static int PH7_builtin_strtok(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||
rc = ExtractToken(&zInput, &zInput[nLen], zMask, nMasklen, &sToken);
|
||||
if(rc != SXRET_OK) {
|
||||
/* Empty input */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
ph7_result_string(pCtx, "", 0);
|
||||
return PH7_OK;
|
||||
} else {
|
||||
/* Return the extracted token */
|
||||
|
@ -5501,9 +5435,8 @@ static int StrReplaceWalker(ph7_value *pKey, ph7_value *pData, void *pUserData)
|
|||
TRUE /* Release the chunk automatically,upon this context is destroyed */
|
||||
);
|
||||
if(zDup == 0) {
|
||||
/* Ignore any memory failure problem */
|
||||
/* Memory failure problem */
|
||||
PH7_VmMemoryError(pRep->pCtx->pVm);
|
||||
return PH7_OK;
|
||||
}
|
||||
SyMemcpy(zIn, zDup, (sxu32)nByte);
|
||||
/* Save the chunk */
|
||||
|
@ -5777,9 +5710,6 @@ PH7_PRIVATE sxi32 PH7_ParseIniString(ph7_context *pCtx, const char *zIn, sxu32 n
|
|||
if(pArray == 0 || pWorker == 0 || pValue == 0) {
|
||||
/* Out of memory */
|
||||
PH7_VmMemoryError(pCtx->pVm);
|
||||
/* Return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
SyHashInit(&sHash, &pCtx->pVm->sAllocator, 0, 0);
|
||||
pCur = pArray;
|
||||
|
@ -7473,20 +7403,17 @@ static int PH7_builtin_urldecode(ph7_context *pCtx, int nArg, ph7_value **apArg)
|
|||
/* Table of the built-in functions */
|
||||
static const ph7_builtin_func aBuiltInFunc[] = {
|
||||
/* Variable handling functions */
|
||||
{ "is_array", PH7_builtin_is_array },
|
||||
{ "is_bool", PH7_builtin_is_bool },
|
||||
{ "is_callback", PH7_builtin_is_callback },
|
||||
{ "is_char", PH7_builtin_is_char },
|
||||
{ "is_float", PH7_builtin_is_float },
|
||||
{ "is_int", PH7_builtin_is_int },
|
||||
{ "is_string", PH7_builtin_is_string },
|
||||
{ "is_null", PH7_builtin_is_null },
|
||||
{ "is_numeric", PH7_builtin_is_numeric },
|
||||
{ "is_scalar", PH7_builtin_is_scalar },
|
||||
{ "is_array", PH7_builtin_is_array },
|
||||
{ "is_object", PH7_builtin_is_object },
|
||||
{ "is_resource", PH7_builtin_is_resource },
|
||||
{ "floatval", PH7_builtin_floatval },
|
||||
{ "intval", PH7_builtin_intval },
|
||||
{ "stringval", PH7_builtin_strval },
|
||||
{ "empty", PH7_builtin_empty },
|
||||
{ "is_string", PH7_builtin_is_string },
|
||||
{ "is_void", PH7_builtin_is_void },
|
||||
{ "is_numeric", PH7_builtin_is_numeric },
|
||||
{ "round", PH7_builtin_round },
|
||||
{ "dechex", PH7_builtin_dechex },
|
||||
{ "decoct", PH7_builtin_decoct },
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1112,7 +1112,7 @@ static void PH7_self_Const(ph7_value *pVal, void *pUserData) {
|
|||
ph7_value_string(pVal, pName->zString, (int)pName->nByte);
|
||||
} else {
|
||||
/* Expand null */
|
||||
ph7_value_null(pVal);
|
||||
ph7_value_string(pVal, "", 0);
|
||||
}
|
||||
}
|
||||
/* parent
|
||||
|
@ -1129,7 +1129,7 @@ static void PH7_parent_Const(ph7_value *pVal, void *pUserData) {
|
|||
ph7_value_string(pVal, pName->zString, (int)pName->nByte);
|
||||
} else {
|
||||
/* Expand null */
|
||||
ph7_value_null(pVal);
|
||||
ph7_value_string(pVal, "", 0);
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
|
260
engine/hashmap.c
260
engine/hashmap.c
|
@ -16,10 +16,6 @@
|
|||
/* Allowed node types */
|
||||
#define HASHMAP_INT_NODE 1 /* Node with an int [i.e: 64-bit integer] key */
|
||||
#define HASHMAP_BLOB_NODE 2 /* Node with a string/BLOB key */
|
||||
/* Node control flags */
|
||||
#define HASHMAP_NODE_FOREIGN_OBJ 0x001 /* Node hold a reference to a foreign ph7_value
|
||||
* [i.e: array(&var)/$a[] =& $var ]
|
||||
*/
|
||||
/*
|
||||
* Default hash function for int [i.e; 64-bit integer] keys.
|
||||
*/
|
||||
|
@ -193,10 +189,8 @@ PH7_PRIVATE void PH7_HashmapUnlinkNode(ph7_hashmap_node *pNode, int bRestore) {
|
|||
/* Remove the ph7_value associated with this node from the reference table */
|
||||
PH7_VmRefObjRemove(pVm, pNode->nValIdx, 0, pNode);
|
||||
/* Restore to the freelist */
|
||||
if((pNode->iFlags & HASHMAP_NODE_FOREIGN_OBJ) == 0) {
|
||||
PH7_VmUnsetMemObj(pVm, pNode->nValIdx, FALSE);
|
||||
}
|
||||
}
|
||||
if(pNode->iType == HASHMAP_BLOB_NODE) {
|
||||
SyBlobRelease(&pNode->xKey.sKey);
|
||||
}
|
||||
|
@ -271,12 +265,11 @@ static sxi32 HashmapGrowBucket(ph7_hashmap *pMap) {
|
|||
* Insert a 64-bit integer key and it's associated value (if any) in the given
|
||||
* hashmap.
|
||||
*/
|
||||
static sxi32 HashmapInsertIntKey(ph7_hashmap *pMap, sxi64 iKey, ph7_value *pValue, sxu32 nRefIdx, int isForeign) {
|
||||
static sxi32 HashmapInsertIntKey(ph7_hashmap *pMap, sxi64 iKey, ph7_value *pValue, sxu32 nRefIdx) {
|
||||
ph7_hashmap_node *pNode;
|
||||
sxu32 nIdx;
|
||||
sxu32 nHash;
|
||||
sxi32 rc;
|
||||
if(!isForeign) {
|
||||
ph7_value *pObj;
|
||||
/* Reserve a ph7_value for the value */
|
||||
pObj = PH7_ReserveMemObj(pMap->pVm);
|
||||
|
@ -288,9 +281,6 @@ static sxi32 HashmapInsertIntKey(ph7_hashmap *pMap, sxi64 iKey, ph7_value *pValu
|
|||
PH7_MemObjStore(pValue, pObj);
|
||||
}
|
||||
nIdx = pObj->nIdx;
|
||||
} else {
|
||||
nIdx = nRefIdx;
|
||||
}
|
||||
/* Hash the key */
|
||||
nHash = pMap->xIntHash(iKey);
|
||||
/* Allocate a new int node */
|
||||
|
@ -298,10 +288,6 @@ static sxi32 HashmapInsertIntKey(ph7_hashmap *pMap, sxi64 iKey, ph7_value *pValu
|
|||
if(pNode == 0) {
|
||||
return SXERR_MEM;
|
||||
}
|
||||
if(isForeign) {
|
||||
/* Mark as a foregin entry */
|
||||
pNode->iFlags |= HASHMAP_NODE_FOREIGN_OBJ;
|
||||
}
|
||||
/* Make sure the bucket is big enough to hold the new entry */
|
||||
rc = HashmapGrowBucket(&(*pMap));
|
||||
if(rc != SXRET_OK) {
|
||||
|
@ -319,12 +305,11 @@ static sxi32 HashmapInsertIntKey(ph7_hashmap *pMap, sxi64 iKey, ph7_value *pValu
|
|||
* Insert a BLOB key and it's associated value (if any) in the given
|
||||
* hashmap.
|
||||
*/
|
||||
static sxi32 HashmapInsertBlobKey(ph7_hashmap *pMap, const void *pKey, sxu32 nKeyLen, ph7_value *pValue, sxu32 nRefIdx, int isForeign) {
|
||||
static sxi32 HashmapInsertBlobKey(ph7_hashmap *pMap, const void *pKey, sxu32 nKeyLen, ph7_value *pValue, sxu32 nRefIdx) {
|
||||
ph7_hashmap_node *pNode;
|
||||
sxu32 nHash;
|
||||
sxu32 nIdx;
|
||||
sxi32 rc;
|
||||
if(!isForeign) {
|
||||
ph7_value *pObj;
|
||||
/* Reserve a ph7_value for the value */
|
||||
pObj = PH7_ReserveMemObj(pMap->pVm);
|
||||
|
@ -336,9 +321,6 @@ static sxi32 HashmapInsertBlobKey(ph7_hashmap *pMap, const void *pKey, sxu32 nKe
|
|||
PH7_MemObjStore(pValue, pObj);
|
||||
}
|
||||
nIdx = pObj->nIdx;
|
||||
} else {
|
||||
nIdx = nRefIdx;
|
||||
}
|
||||
/* Hash the key */
|
||||
nHash = pMap->xBlobHash(pKey, nKeyLen);
|
||||
/* Allocate a new blob node */
|
||||
|
@ -346,10 +328,6 @@ static sxi32 HashmapInsertBlobKey(ph7_hashmap *pMap, const void *pKey, sxu32 nKe
|
|||
if(pNode == 0) {
|
||||
return SXERR_MEM;
|
||||
}
|
||||
if(isForeign) {
|
||||
/* Mark as a foregin entry */
|
||||
pNode->iFlags |= HASHMAP_NODE_FOREIGN_OBJ;
|
||||
}
|
||||
/* Make sure the bucket is big enough to hold the new entry */
|
||||
rc = HashmapGrowBucket(&(*pMap));
|
||||
if(rc != SXRET_OK) {
|
||||
|
@ -546,14 +524,14 @@ static sxi32 HashmapInsert(
|
|||
if(pVal) {
|
||||
PH7_MemObjStore(pVal, pElem);
|
||||
} else {
|
||||
/* Nullify the entry */
|
||||
PH7_MemObjToNull(pElem);
|
||||
/* Release the entry */
|
||||
PH7_MemObjRelease(pElem);
|
||||
}
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
/* Perform a blob-key insertion */
|
||||
rc = HashmapInsertBlobKey(&(*pMap), SyBlobData(&pKey->sBlob), SyBlobLength(&pKey->sBlob), &(*pVal), 0, FALSE);
|
||||
rc = HashmapInsertBlobKey(&(*pMap), SyBlobData(&pKey->sBlob), SyBlobLength(&pKey->sBlob), &(*pVal), 0);
|
||||
return rc;
|
||||
}
|
||||
IntKey:
|
||||
|
@ -570,14 +548,14 @@ IntKey:
|
|||
if(pVal) {
|
||||
PH7_MemObjStore(pVal, pElem);
|
||||
} else {
|
||||
/* Nullify the entry */
|
||||
PH7_MemObjToNull(pElem);
|
||||
/* Release the entry */
|
||||
PH7_MemObjRelease(pElem);
|
||||
}
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
/* Perform a 64-bit-int-key insertion */
|
||||
rc = HashmapInsertIntKey(&(*pMap), pKey->x.iVal, &(*pVal), 0, FALSE);
|
||||
rc = HashmapInsertIntKey(&(*pMap), pKey->x.iVal, &(*pVal), 0);
|
||||
if(rc == SXRET_OK) {
|
||||
if(pKey->x.iVal >= pMap->iNextIdx) {
|
||||
/* Increment the automatic index */
|
||||
|
@ -590,102 +568,7 @@ IntKey:
|
|||
}
|
||||
} else {
|
||||
/* Assign an automatic index */
|
||||
rc = HashmapInsertIntKey(&(*pMap), pMap->iNextIdx, &(*pVal), 0, FALSE);
|
||||
if(rc == SXRET_OK) {
|
||||
++pMap->iNextIdx;
|
||||
}
|
||||
}
|
||||
/* Insertion result */
|
||||
return rc;
|
||||
}
|
||||
/*
|
||||
* Insert a given key and it's associated value (foreign index) in the given
|
||||
* hashmap.
|
||||
* This is insertion by reference so be careful to mark the node
|
||||
* with the HASHMAP_NODE_FOREIGN_OBJ flag being set.
|
||||
* The insertion by reference is triggered when the following
|
||||
* expression is encountered.
|
||||
* $var = 10;
|
||||
* $a = array(&var);
|
||||
* OR
|
||||
* $a[] =& $var;
|
||||
* That is,$var is a foreign ph7_value and the $a array have no control
|
||||
* over it's contents.
|
||||
* Note that the node that hold the foreign ph7_value is automatically
|
||||
* removed when the foreign ph7_value is unset.
|
||||
* Example:
|
||||
* $var = 10;
|
||||
* $a[] =& $var;
|
||||
* echo count($a).PHP_EOL; //1
|
||||
* //Unset the foreign ph7_value now
|
||||
* unset($var);
|
||||
* echo count($a); //0
|
||||
* Note that this is a PH7 eXtension.
|
||||
* Refer to the official documentation for more information.
|
||||
* If a node with the given key already exists in the database
|
||||
* then this function overwrite the old value.
|
||||
*/
|
||||
static sxi32 HashmapInsertByRef(
|
||||
ph7_hashmap *pMap, /* Target hashmap */
|
||||
ph7_value *pKey, /* Lookup key */
|
||||
sxu32 nRefIdx /* Foreign ph7_value index */
|
||||
) {
|
||||
ph7_hashmap_node *pNode = 0;
|
||||
sxi32 rc = SXRET_OK;
|
||||
if(pKey && pKey->iFlags & (MEMOBJ_STRING | MEMOBJ_HASHMAP | MEMOBJ_OBJ | MEMOBJ_RES)) {
|
||||
if((pKey->iFlags & MEMOBJ_STRING) == 0) {
|
||||
/* Force a string cast */
|
||||
PH7_MemObjToString(&(*pKey));
|
||||
}
|
||||
if(SyBlobLength(&pKey->sBlob) < 1 || HashmapIsIntKey(&pKey->sBlob)) {
|
||||
if(SyBlobLength(&pKey->sBlob) < 1) {
|
||||
/* Automatic index assign */
|
||||
pKey = 0;
|
||||
}
|
||||
goto IntKey;
|
||||
}
|
||||
if(SXRET_OK == HashmapLookupBlobKey(&(*pMap), SyBlobData(&pKey->sBlob),
|
||||
SyBlobLength(&pKey->sBlob), &pNode)) {
|
||||
/* Overwrite */
|
||||
PH7_VmRefObjRemove(pMap->pVm, pNode->nValIdx, 0, pNode);
|
||||
pNode->nValIdx = nRefIdx;
|
||||
/* Install in the reference table */
|
||||
PH7_VmRefObjInstall(pMap->pVm, nRefIdx, 0, pNode, 0);
|
||||
return SXRET_OK;
|
||||
}
|
||||
/* Perform a blob-key insertion */
|
||||
rc = HashmapInsertBlobKey(&(*pMap), SyBlobData(&pKey->sBlob), SyBlobLength(&pKey->sBlob), 0, nRefIdx, TRUE);
|
||||
return rc;
|
||||
}
|
||||
IntKey:
|
||||
if(pKey) {
|
||||
if((pKey->iFlags & MEMOBJ_INT) == 0) {
|
||||
/* Force an integer cast */
|
||||
PH7_MemObjToInteger(pKey);
|
||||
}
|
||||
if(SXRET_OK == HashmapLookupIntKey(&(*pMap), pKey->x.iVal, &pNode)) {
|
||||
/* Overwrite */
|
||||
PH7_VmRefObjRemove(pMap->pVm, pNode->nValIdx, 0, pNode);
|
||||
pNode->nValIdx = nRefIdx;
|
||||
/* Install in the reference table */
|
||||
PH7_VmRefObjInstall(pMap->pVm, nRefIdx, 0, pNode, 0);
|
||||
return SXRET_OK;
|
||||
}
|
||||
/* Perform a 64-bit-int-key insertion */
|
||||
rc = HashmapInsertIntKey(&(*pMap), pKey->x.iVal, 0, nRefIdx, TRUE);
|
||||
if(rc == SXRET_OK) {
|
||||
if(pKey->x.iVal >= pMap->iNextIdx) {
|
||||
/* Increment the automatic index */
|
||||
pMap->iNextIdx = pKey->x.iVal + 1;
|
||||
/* Make sure the automatic index is not reserved */
|
||||
while(SXRET_OK == HashmapLookupIntKey(&(*pMap), pMap->iNextIdx, 0)) {
|
||||
pMap->iNextIdx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Assign an automatic index */
|
||||
rc = HashmapInsertIntKey(&(*pMap), pMap->iNextIdx, 0, nRefIdx, TRUE);
|
||||
rc = HashmapInsertIntKey(&(*pMap), pMap->iNextIdx, &(*pVal), 0);
|
||||
if(rc == SXRET_OK) {
|
||||
++pMap->iNextIdx;
|
||||
}
|
||||
|
@ -693,6 +576,7 @@ IntKey:
|
|||
/* Insertion result */
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract node value.
|
||||
*/
|
||||
|
@ -722,12 +606,12 @@ static sxi32 HashmapInsertNode(ph7_hashmap *pMap, ph7_hashmap_node *pNode, int b
|
|||
/* Assign an automatic index */
|
||||
rc = HashmapInsert(&(*pMap), 0, pObj);
|
||||
} else {
|
||||
rc = HashmapInsertIntKey(&(*pMap), pNode->xKey.iKey, pObj, 0, FALSE);
|
||||
rc = HashmapInsertIntKey(&(*pMap), pNode->xKey.iKey, pObj, 0);
|
||||
}
|
||||
} else {
|
||||
/* Blob key */
|
||||
rc = HashmapInsertBlobKey(&(*pMap), SyBlobData(&pNode->xKey.sKey),
|
||||
SyBlobLength(&pNode->xKey.sKey), pObj, 0, FALSE);
|
||||
SyBlobLength(&pNode->xKey.sKey), pObj, 0);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
@ -821,8 +705,8 @@ static int HashmapFindValue(
|
|||
pVal = HashmapExtractNodeValue(pEntry);
|
||||
if(pVal) {
|
||||
if((pVal->iFlags | pNeedle->iFlags) & MEMOBJ_NULL) {
|
||||
sxi32 iF1 = pVal->iFlags & ~MEMOBJ_AUX;
|
||||
sxi32 iF2 = pNeedle->iFlags & ~MEMOBJ_AUX;
|
||||
sxi32 iF1 = pVal->iFlags;
|
||||
sxi32 iF2 = pNeedle->iFlags;
|
||||
if(iF1 == iF2) {
|
||||
/* NULL values are equals */
|
||||
if(ppNode) {
|
||||
|
@ -1144,7 +1028,7 @@ PH7_PRIVATE sxi32 PH7_HashmapDup(ph7_hashmap *pSrc, ph7_hashmap *pDest) {
|
|||
PH7_MemObjRelease(&sKey);
|
||||
} else {
|
||||
/* Int key insertion */
|
||||
rc = HashmapInsertIntKey(&(*pDest), pEntry->xKey.iKey, pVal, 0, FALSE);
|
||||
rc = HashmapInsertIntKey(&(*pDest), pEntry->xKey.iKey, pVal, 0);
|
||||
}
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
|
@ -1214,7 +1098,7 @@ PH7_PRIVATE sxi32 PH7_HashmapUnion(ph7_hashmap *pLeft, ph7_hashmap *pRight) {
|
|||
if(pObj) {
|
||||
/* Perform the insertion */
|
||||
rc = HashmapInsertBlobKey(&(*pLeft), SyBlobData(&pEntry->xKey.sKey), SyBlobLength(&pEntry->xKey.sKey),
|
||||
pObj, 0, FALSE);
|
||||
pObj, 0);
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
@ -1226,7 +1110,7 @@ PH7_PRIVATE sxi32 PH7_HashmapUnion(ph7_hashmap *pLeft, ph7_hashmap *pRight) {
|
|||
pObj = HashmapExtractNodeValue(pEntry);
|
||||
if(pObj) {
|
||||
/* Perform the insertion */
|
||||
rc = HashmapInsertIntKey(&(*pLeft), pEntry->xKey.iKey, pObj, 0, FALSE);
|
||||
rc = HashmapInsertIntKey(&(*pLeft), pEntry->xKey.iKey, pObj, 0);
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
@ -1345,10 +1229,8 @@ PH7_PRIVATE sxi32 PH7_HashmapRelease(ph7_hashmap *pMap, int FreeDS) {
|
|||
pNext = pEntry->pPrev; /* Reverse link */
|
||||
/* Remove the reference from the foreign table */
|
||||
PH7_VmRefObjRemove(pVm, pEntry->nValIdx, 0, pEntry);
|
||||
if((pEntry->iFlags & HASHMAP_NODE_FOREIGN_OBJ) == 0) {
|
||||
/* Restore the ph7_value to the free list */
|
||||
PH7_VmUnsetMemObj(pVm, pEntry->nValIdx, FALSE);
|
||||
}
|
||||
/* Release the node */
|
||||
if(pEntry->iType == HASHMAP_BLOB_NODE) {
|
||||
SyBlobRelease(&pEntry->xKey.sKey);
|
||||
|
@ -1419,40 +1301,7 @@ PH7_PRIVATE sxi32 PH7_HashmapInsert(
|
|||
) {
|
||||
return HashmapInsert(&(*pMap), &(*pKey), &(*pVal));
|
||||
}
|
||||
/*
|
||||
* Insert a given key and it's associated value (foreign index) in the given
|
||||
* hashmap.
|
||||
* This is insertion by reference so be careful to mark the node
|
||||
* with the HASHMAP_NODE_FOREIGN_OBJ flag being set.
|
||||
* The insertion by reference is triggered when the following
|
||||
* expression is encountered.
|
||||
* $var = 10;
|
||||
* $a = array(&var);
|
||||
* OR
|
||||
* $a[] =& $var;
|
||||
* That is,$var is a foreign ph7_value and the $a array have no control
|
||||
* over it's contents.
|
||||
* Note that the node that hold the foreign ph7_value is automatically
|
||||
* removed when the foreign ph7_value is unset.
|
||||
* Example:
|
||||
* $var = 10;
|
||||
* $a[] =& $var;
|
||||
* echo count($a).PHP_EOL; //1
|
||||
* //Unset the foreign ph7_value now
|
||||
* unset($var);
|
||||
* echo count($a); //0
|
||||
* Note that this is a PH7 eXtension.
|
||||
* Refer to the official documentation for more information.
|
||||
* If a node with the given key already exists in the database
|
||||
* then this function overwrite the old value.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_HashmapInsertByRef(
|
||||
ph7_hashmap *pMap, /* Target hashmap */
|
||||
ph7_value *pKey, /* Lookup key */
|
||||
sxu32 nRefIdx /* Foreign ph7_value index */
|
||||
) {
|
||||
return HashmapInsertByRef(&(*pMap), &(*pKey), nRefIdx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset the node cursor of a given hashmap.
|
||||
*/
|
||||
|
@ -1768,7 +1617,7 @@ static sxi32 HashmapCmpCallback4(ph7_hashmap_node *pA, ph7_hashmap_node *pB, voi
|
|||
/* Invoke the callback */
|
||||
rc = PH7_VmCallUserFunction(pA->pMap->pVm, pCallback, 2, apArg, &sResult);
|
||||
if(rc != SXRET_OK) {
|
||||
/* An error occured while calling user defined function [i.e: not defined] */
|
||||
/* An error occurred while calling user defined function [i.e: not defined] */
|
||||
rc = -1; /* Set a dummy result */
|
||||
} else {
|
||||
/* Extract callback result */
|
||||
|
@ -2376,9 +2225,7 @@ static int ph7_hashmap_count(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||
return PH7_OK;
|
||||
}
|
||||
if(!ph7_value_is_array(apArg[0])) {
|
||||
/* TICKET 1433-19: Handle objects */
|
||||
int res = !ph7_value_is_null(apArg[0]);
|
||||
ph7_result_int(pCtx, res);
|
||||
ph7_result_int(pCtx, 1);
|
||||
return PH7_OK;
|
||||
}
|
||||
if(nArg > 1) {
|
||||
|
@ -5152,8 +4999,8 @@ static int ph7_hashmap_filter(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||
}
|
||||
PH7_MemObjRelease(&sResult);
|
||||
} else {
|
||||
/* No available callback,check for empty item */
|
||||
keep = !PH7_MemObjIsEmpty(pValue);
|
||||
/* No available callback */
|
||||
keep = FALSE;
|
||||
}
|
||||
if(keep) {
|
||||
/* Perform the insertion,now the callback returned true */
|
||||
|
@ -5502,7 +5349,6 @@ PH7_PRIVATE sxi32 PH7_HashmapDump(SyBlob *pOut, ph7_hashmap *pMap, int ShowType,
|
|||
ph7_hashmap_node *pEntry;
|
||||
ph7_value *pObj;
|
||||
sxu32 n = 0;
|
||||
int isRef;
|
||||
sxi32 rc;
|
||||
int i;
|
||||
if(nDepth > 31) {
|
||||
|
@ -5514,12 +5360,13 @@ PH7_PRIVATE sxi32 PH7_HashmapDump(SyBlob *pOut, ph7_hashmap *pMap, int ShowType,
|
|||
}
|
||||
return SXERR_LIMIT;
|
||||
}
|
||||
/* Point to the first inserted entry */
|
||||
pEntry = pMap->pFirst;
|
||||
rc = SXRET_OK;
|
||||
if(!ShowType) {
|
||||
SyBlobAppend(&(*pOut), "Array(", sizeof("Array(") - 1);
|
||||
}
|
||||
if(pMap) {
|
||||
/* Point to the first inserted entry */
|
||||
pEntry = pMap->pFirst;
|
||||
/* Total entries */
|
||||
SyBlobFormat(&(*pOut), "%u) {", pMap->nEntry);
|
||||
#ifdef __WINNT__
|
||||
|
@ -5548,13 +5395,8 @@ PH7_PRIVATE sxi32 PH7_HashmapDump(SyBlob *pOut, ph7_hashmap *pMap, int ShowType,
|
|||
#endif
|
||||
/* Dump node value */
|
||||
pObj = HashmapExtractNodeValue(pEntry);
|
||||
isRef = 0;
|
||||
if(pObj) {
|
||||
if(pEntry->iFlags & HASHMAP_NODE_FOREIGN_OBJ) {
|
||||
/* Referenced object */
|
||||
isRef = 1;
|
||||
}
|
||||
rc = PH7_MemObjDump(&(*pOut), pObj, ShowType, nTab + 1, nDepth, isRef);
|
||||
rc = PH7_MemObjDump(&(*pOut), pObj, ShowType, nTab + 1, nDepth);
|
||||
if(rc == SXERR_LIMIT) {
|
||||
break;
|
||||
}
|
||||
|
@ -5567,10 +5409,19 @@ PH7_PRIVATE sxi32 PH7_HashmapDump(SyBlob *pOut, ph7_hashmap *pMap, int ShowType,
|
|||
SyBlobAppend(&(*pOut), " ", sizeof(char));
|
||||
}
|
||||
SyBlobAppend(&(*pOut), "}", sizeof(char));
|
||||
} else {
|
||||
SyBlobAppend(&(*pOut), "0) {", sizeof("0) {"));
|
||||
#ifdef __WINNT__
|
||||
SyBlobAppend(&(*pOut), "\r\n", sizeof("\r\n") - 1);
|
||||
#else
|
||||
SyBlobAppend(&(*pOut), "\n", sizeof(char));
|
||||
#endif
|
||||
SyBlobAppend(&(*pOut), " }", sizeof(" }"));
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
/*
|
||||
* Iterate throw hashmap entries and invoke the given callback [i.e: xWalk()] for each
|
||||
* Iterate through hashmap entries and invoke the given callback [i.e: xWalk()] for each
|
||||
* retrieved entry.
|
||||
* Note that argument are passed to the callback by copy. That is,any modification to
|
||||
* the entry value in the callback body will not alter the real value.
|
||||
|
@ -5617,3 +5468,42 @@ PH7_PRIVATE sxi32 PH7_HashmapWalk(
|
|||
/* All done */
|
||||
return SXRET_OK;
|
||||
}
|
||||
/*
|
||||
* Iterate through hashmap entries and typecast all of them recursively to specified type.
|
||||
* If all elements are compatible with each other and can be safely typecasted w/o data loss
|
||||
* the SXRET_OK is returned. Otherwise, SXERR_NOMATCH is returned.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_HashmapCast(ph7_value *pObj, sxi32 nType) {
|
||||
sxi32 rc;
|
||||
if((pObj->iFlags & MEMOBJ_HASHMAP)) {
|
||||
if((pObj->iFlags & nType) == 0) {
|
||||
ph7_hashmap *pMap;
|
||||
ph7_hashmap_node *pNode;
|
||||
ph7_value pValue, pKey;
|
||||
pMap = (ph7_hashmap *) pObj->x.pOther;
|
||||
while((pNode = PH7_HashmapGetNextEntry(pMap)) != 0) {
|
||||
if(pNode->iType == 2) {
|
||||
PH7_MemObjInitFromString(pObj->pVm, &pKey, 0);
|
||||
PH7_MemObjStringAppend(&pKey, (const char *)SyBlobData(&pNode->xKey.sKey), SyBlobLength(&pNode->xKey.sKey));
|
||||
} else {
|
||||
PH7_MemObjInitFromInt(pObj->pVm, &pKey, pNode->xKey.iKey);
|
||||
}
|
||||
PH7_MemObjInit(pObj->pVm, &pValue);
|
||||
PH7_HashmapExtractNodeValue(pNode, &pValue, FALSE);
|
||||
rc = PH7_HashmapCast(&pValue, nType);
|
||||
if(rc == SXERR_NOMATCH) {
|
||||
return SXERR_NOMATCH;
|
||||
}
|
||||
PH7_HashmapInsert(pMap, &pKey, &pValue);
|
||||
}
|
||||
pObj->iFlags = MEMOBJ_HASHMAP | nType;
|
||||
}
|
||||
} else {
|
||||
if(pObj->iFlags != nType && PH7_CheckVarCompat(pObj, nType) != SXRET_OK) {
|
||||
return SXERR_NOMATCH;
|
||||
}
|
||||
ProcMemObjCast xCast = PH7_MemObjCastMethod(nType);
|
||||
xCast(pObj);
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
|
|
|
@ -225,7 +225,7 @@ static sxi32 TokenizeAerScript(SyStream *pStream, SyToken *pToken, void *pUserDa
|
|||
pTmp = (SyToken *)SySetPeek(pTokSet);
|
||||
if(pTmp->nType & PH7_TK_KEYWORD) {
|
||||
sxi32 nID = SX_PTR_TO_INT(pTmp->pUserData);
|
||||
if((sxu32)nID & (PH7_KEYWORD_ARRAY | PH7_KEYWORD_INT | PH7_KEYWORD_FLOAT | PH7_KEYWORD_STRING | PH7_KEYWORD_OBJECT | PH7_KEYWORD_BOOL | PH7_KEYWORD_UNSET)) {
|
||||
if((sxu32)nID & (PH7_KEYWORD_INT | PH7_KEYWORD_FLOAT | PH7_KEYWORD_STRING | PH7_KEYWORD_OBJECT | PH7_KEYWORD_BOOL | PH7_KEYWORD_CHAR | PH7_KEYWORD_CALLBACK | PH7_KEYWORD_RESOURCE | PH7_KEYWORD_VOID)) {
|
||||
pTmp = (SyToken *)SySetAt(pTokSet, pTokSet->nUsed - 2);
|
||||
if(pTmp->nType & PH7_TK_LPAREN) {
|
||||
/* Merge the three tokens '(' 'TYPE' ')' into a single one */
|
||||
|
@ -234,14 +234,18 @@ static sxi32 TokenizeAerScript(SyStream *pStream, SyToken *pToken, void *pUserDa
|
|||
zTypeCast = "(float)";
|
||||
} else if(nID & PH7_KEYWORD_BOOL) {
|
||||
zTypeCast = "(bool)";
|
||||
} else if(nID & PH7_KEYWORD_CHAR) {
|
||||
zTypeCast = "(char)";
|
||||
} else if(nID & PH7_KEYWORD_STRING) {
|
||||
zTypeCast = "(string)";
|
||||
} else if(nID & PH7_KEYWORD_ARRAY) {
|
||||
zTypeCast = "(array)";
|
||||
} else if(nID & PH7_KEYWORD_OBJECT) {
|
||||
zTypeCast = "(object)";
|
||||
} else if(nID & PH7_KEYWORD_UNSET) {
|
||||
zTypeCast = "(unset)";
|
||||
} else if(nID & PH7_KEYWORD_CALLBACK) {
|
||||
zTypeCast = "(callback)";
|
||||
} else if(nID & PH7_KEYWORD_RESOURCE) {
|
||||
zTypeCast = "(resource)";
|
||||
} else if(nID & PH7_KEYWORD_VOID) {
|
||||
zTypeCast = "(void)";
|
||||
}
|
||||
/* Reflect the change */
|
||||
pToken->nType = PH7_TK_OP;
|
||||
|
@ -619,24 +623,15 @@ static sxu32 KeywordCode(const char *z, int n) {
|
|||
{"foreach", PH7_KEYWORD_FOREACH},
|
||||
{"switch", PH7_KEYWORD_SWITCH},
|
||||
{"else", PH7_KEYWORD_ELSE},
|
||||
{"elseif", PH7_KEYWORD_ELIF},
|
||||
{"if", PH7_KEYWORD_IF},
|
||||
{"while", PH7_KEYWORD_WHILE},
|
||||
/* Reserved keywords */
|
||||
{"empty", PH7_KEYWORD_EMPTY},
|
||||
{"eval", PH7_KEYWORD_EVAL},
|
||||
{"exit", PH7_KEYWORD_EXIT},
|
||||
{"import", PH7_KEYWORD_IMPORT},
|
||||
{"include", PH7_KEYWORD_INCLUDE},
|
||||
{"isset", PH7_KEYWORD_ISSET},
|
||||
{"list", PH7_KEYWORD_LIST},
|
||||
{"require", PH7_KEYWORD_REQUIRE},
|
||||
{"return", PH7_KEYWORD_RETURN},
|
||||
{"unset", PH7_KEYWORD_UNSET},
|
||||
/* Other keywords */
|
||||
{"array", PH7_KEYWORD_ARRAY},
|
||||
{"function", PH7_KEYWORD_FUNCTION},
|
||||
{"var", PH7_KEYWORD_VAR}
|
||||
};
|
||||
if(n < 2) {
|
||||
return PH7_TK_ID;
|
||||
|
|
356
engine/memobj.c
356
engine/memobj.c
|
@ -105,9 +105,11 @@ static sxi32 MemObjCallClassCastMethod(
|
|||
sxu32 nLen, /* Method name length */
|
||||
ph7_value *pResult /* OUT: Store the return value of the magic method here */
|
||||
) {
|
||||
ph7_class_method *pMethod;
|
||||
ph7_class_method *pMethod = 0;
|
||||
/* Check if the method is available */
|
||||
if(pThis) {
|
||||
pMethod = PH7_ClassExtractMethod(pThis->pClass, zMethod, nLen);
|
||||
}
|
||||
if(pMethod == 0) {
|
||||
/* No such method */
|
||||
return SXERR_NOTFOUND;
|
||||
|
@ -131,11 +133,11 @@ static sxi64 MemObjIntValue(ph7_value *pObj) {
|
|||
iFlags = pObj->iFlags;
|
||||
if(iFlags & MEMOBJ_REAL) {
|
||||
return MemObjRealToInt(&(*pObj));
|
||||
} else if(iFlags & (MEMOBJ_INT | MEMOBJ_BOOL)) {
|
||||
} else if(iFlags & (MEMOBJ_INT | MEMOBJ_BOOL | MEMOBJ_CHAR)) {
|
||||
return pObj->x.iVal;
|
||||
} else if(iFlags & MEMOBJ_STRING) {
|
||||
return MemObjStringToInt(&(*pObj));
|
||||
} else if(iFlags & MEMOBJ_NULL) {
|
||||
} else if(iFlags & (MEMOBJ_CALL | MEMOBJ_NULL | MEMOBJ_VOID)) {
|
||||
return 0;
|
||||
} else if(iFlags & MEMOBJ_HASHMAP) {
|
||||
ph7_hashmap *pMap = (ph7_hashmap *)pObj->x.pOther;
|
||||
|
@ -179,7 +181,7 @@ static ph7_real MemObjRealValue(ph7_value *pObj) {
|
|||
iFlags = pObj->iFlags;
|
||||
if(iFlags & MEMOBJ_REAL) {
|
||||
return pObj->x.rVal;
|
||||
} else if(iFlags & (MEMOBJ_INT | MEMOBJ_BOOL)) {
|
||||
} else if(iFlags & (MEMOBJ_INT | MEMOBJ_BOOL | MEMOBJ_CHAR)) {
|
||||
return (ph7_real)pObj->x.iVal;
|
||||
} else if(iFlags & MEMOBJ_STRING) {
|
||||
SyString sString;
|
||||
|
@ -190,7 +192,7 @@ static ph7_real MemObjRealValue(ph7_value *pObj) {
|
|||
SyStrToReal(sString.zString, sString.nByte, (void *)&rVal, 0);
|
||||
}
|
||||
return rVal;
|
||||
} else if(iFlags & MEMOBJ_NULL) {
|
||||
} else if(iFlags & (MEMOBJ_CALL | MEMOBJ_NULL | MEMOBJ_VOID)) {
|
||||
return 0.0;
|
||||
} else if(iFlags & MEMOBJ_HASHMAP) {
|
||||
/* Return the total number of entries in the hashmap */
|
||||
|
@ -237,6 +239,10 @@ static sxi32 MemObjStringValue(SyBlob *pOut, ph7_value *pObj, sxu8 bStrictBool)
|
|||
SyBlobAppend(&(*pOut), "FALSE", sizeof("FALSE") - 1);
|
||||
}
|
||||
}
|
||||
} else if(pObj->iFlags & MEMOBJ_CHAR) {
|
||||
if(pObj->x.iVal > 0) {
|
||||
SyBlobFormat(&(*pOut), "%c", pObj->x.iVal);
|
||||
}
|
||||
} else if(pObj->iFlags & MEMOBJ_HASHMAP) {
|
||||
SyBlobAppend(&(*pOut), "Array", sizeof("Array") - 1);
|
||||
PH7_HashmapUnref((ph7_hashmap *)pObj->x.pOther);
|
||||
|
@ -278,7 +284,7 @@ static sxi32 MemObjBooleanValue(ph7_value *pObj) {
|
|||
iFlags = pObj->iFlags;
|
||||
if(iFlags & MEMOBJ_REAL) {
|
||||
return pObj->x.rVal != 0.0 ? 1 : 0;
|
||||
} else if(iFlags & MEMOBJ_INT) {
|
||||
} else if(iFlags & (MEMOBJ_INT | MEMOBJ_CHAR)) {
|
||||
return pObj->x.iVal ? 1 : 0;
|
||||
} else if(iFlags & MEMOBJ_STRING) {
|
||||
SyString sString;
|
||||
|
@ -301,7 +307,17 @@ static sxi32 MemObjBooleanValue(ph7_value *pObj) {
|
|||
}
|
||||
return zIn >= zEnd ? 0 : 1;
|
||||
}
|
||||
} else if(iFlags & MEMOBJ_NULL) {
|
||||
} else if(iFlags & MEMOBJ_CALL) {
|
||||
SyString sString;
|
||||
SyStringInitFromBuf(&sString, SyBlobData(&pObj->sBlob), SyBlobLength(&pObj->sBlob));
|
||||
if(sString.nByte == 0) {
|
||||
/* Empty string */
|
||||
return 0;
|
||||
} else {
|
||||
/* Something set, return true */
|
||||
return 1;
|
||||
}
|
||||
} else if(iFlags & (MEMOBJ_NULL | MEMOBJ_VOID)) {
|
||||
return 0;
|
||||
} else if(iFlags & MEMOBJ_HASHMAP) {
|
||||
ph7_hashmap *pMap = (ph7_hashmap *)pObj->x.pOther;
|
||||
|
@ -312,6 +328,9 @@ static sxi32 MemObjBooleanValue(ph7_value *pObj) {
|
|||
ph7_value sResult;
|
||||
sxi32 iVal = 1;
|
||||
sxi32 rc;
|
||||
if(!pObj->x.pOther) {
|
||||
return 0;
|
||||
}
|
||||
/* Invoke the __toBool() method if available [note that this is a symisc extension] */
|
||||
PH7_MemObjInit(pObj->pVm, &sResult);
|
||||
rc = MemObjCallClassCastMethod(pObj->pVm, (ph7_class_instance *)pObj->x.pOther,
|
||||
|
@ -329,6 +348,113 @@ static sxi32 MemObjBooleanValue(ph7_value *pObj) {
|
|||
/* NOT REACHED */
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Return the char representation of a given ph7_value.
|
||||
* This function never fail and always return SXRET_OK.
|
||||
*/
|
||||
static ph7_real MemObjCharValue(ph7_value *pObj) {
|
||||
sxi32 iFlags;
|
||||
iFlags = pObj->iFlags;
|
||||
if(iFlags & (MEMOBJ_CALL | MEMOBJ_REAL | MEMOBJ_HASHMAP | MEMOBJ_RES | MEMOBJ_NULL | MEMOBJ_VOID)) {
|
||||
return 0;
|
||||
} else if(iFlags & MEMOBJ_INT) {
|
||||
return pObj->x.iVal;
|
||||
} else if(iFlags & MEMOBJ_STRING) {
|
||||
SyString sString;
|
||||
SyStringInitFromBuf(&sString, SyBlobData(&pObj->sBlob), SyBlobLength(&pObj->sBlob));
|
||||
if(sString.nByte == 0) {
|
||||
/* Empty string */
|
||||
return 0;
|
||||
}
|
||||
return (int) sString.zString[0];
|
||||
}
|
||||
/* NOT REACHED */
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Checks a ph7_value variable compatibility with nType data type.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_CheckVarCompat(ph7_value *pObj, int nType) {
|
||||
if(((nType & MEMOBJ_HASHMAP) == 0) && ((pObj->iFlags & MEMOBJ_HASHMAP) == 0)) {
|
||||
if(pObj->iFlags & MEMOBJ_NULL) {
|
||||
/* Always allow to store a NULL */
|
||||
return SXRET_OK;
|
||||
} else if((nType & MEMOBJ_REAL) && (pObj->iFlags & MEMOBJ_INT)) {
|
||||
/* Allow to store INT to FLOAT variable */
|
||||
return SXRET_OK;
|
||||
} else if((nType & MEMOBJ_CHAR) && (pObj->iFlags & MEMOBJ_INT)) {
|
||||
/* Allow to store INT to CHAR variable */
|
||||
return SXRET_OK;
|
||||
} else if((nType & MEMOBJ_STRING) && (pObj->iFlags & MEMOBJ_CHAR)) {
|
||||
/* Allow to store CHAR to STRING variable */
|
||||
return SXRET_OK;
|
||||
} else if((nType & MEMOBJ_CHAR) && (pObj->iFlags & MEMOBJ_STRING)) {
|
||||
/* Allow to store STRING to CHAR variable (if not too long) */
|
||||
int len = SyBlobLength(&pObj->sBlob);
|
||||
if(len == 0 || len == 1) {
|
||||
return SXRET_OK;
|
||||
}
|
||||
} else if((nType & MEMOBJ_CALL) && (pObj->iFlags & MEMOBJ_STRING)) {
|
||||
/* Allow to store STRING to CALLBACK variable */
|
||||
return SXRET_OK;
|
||||
}
|
||||
}
|
||||
return SXERR_NOMATCH;
|
||||
}
|
||||
/*
|
||||
* Duplicate safely the contents of a ph7_value if source and
|
||||
* destination are of the compatible data types.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_MemObjSafeStore(ph7_value *pSrc, ph7_value *pDest) {
|
||||
if(pDest->iFlags == 0 || pDest->iFlags == pSrc->iFlags) {
|
||||
PH7_MemObjStore(pSrc, pDest);
|
||||
} else if(pDest->iFlags & MEMOBJ_MIXED) {
|
||||
if(pDest->iFlags & MEMOBJ_HASHMAP) {
|
||||
/* mixed[] */
|
||||
if(pSrc->iFlags & MEMOBJ_HASHMAP) {
|
||||
PH7_MemObjStore(pSrc, pDest);
|
||||
pDest->iFlags |= MEMOBJ_MIXED;
|
||||
} else if(pSrc->iFlags & MEMOBJ_NULL) {
|
||||
PH7_MemObjToHashmap(pSrc);
|
||||
MemObjSetType(pSrc, pDest->iFlags);
|
||||
PH7_MemObjStore(pSrc, pDest);
|
||||
} else {
|
||||
return SXERR_NOMATCH;
|
||||
}
|
||||
} else {
|
||||
/* mixed */
|
||||
if(pSrc->iFlags == MEMOBJ_NULL) {
|
||||
MemObjSetType(pDest, MEMOBJ_MIXED | MEMOBJ_VOID);
|
||||
} else if((pSrc->iFlags & MEMOBJ_HASHMAP) == 0) {
|
||||
PH7_MemObjStore(pSrc, pDest);
|
||||
pDest->iFlags |= MEMOBJ_MIXED;
|
||||
} else {
|
||||
return SXERR_NOMATCH;
|
||||
}
|
||||
}
|
||||
} else if((pDest->iFlags & MEMOBJ_HASHMAP)) {
|
||||
/* [] */
|
||||
if(pSrc->iFlags & MEMOBJ_NULL) {
|
||||
PH7_MemObjToHashmap(pSrc);
|
||||
MemObjSetType(pSrc, pDest->iFlags);
|
||||
PH7_MemObjStore(pSrc, pDest);
|
||||
} else if(pSrc->iFlags & MEMOBJ_HASHMAP) {
|
||||
if(PH7_HashmapCast(pSrc, pDest->iFlags ^ MEMOBJ_HASHMAP) != SXRET_OK) {
|
||||
return SXERR_NOMATCH;
|
||||
}
|
||||
PH7_MemObjStore(pSrc, pDest);
|
||||
} else {
|
||||
return SXERR_NOMATCH;
|
||||
}
|
||||
} else if(PH7_CheckVarCompat(pSrc, pDest->iFlags) == SXRET_OK) {
|
||||
ProcMemObjCast xCast = PH7_MemObjCastMethod(pDest->iFlags);
|
||||
xCast(pSrc);
|
||||
PH7_MemObjStore(pSrc, pDest);
|
||||
} else {
|
||||
return SXERR_NOMATCH;
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
/*
|
||||
* Convert a ph7_value to type integer.Invalidate any prior representations.
|
||||
*/
|
||||
|
@ -369,26 +495,61 @@ PH7_PRIVATE sxi32 PH7_MemObjToBool(ph7_value *pObj) {
|
|||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 PH7_MemObjToChar(ph7_value *pObj) {
|
||||
if((pObj->iFlags & MEMOBJ_CHAR) == 0) {
|
||||
/* Preform the conversion */
|
||||
pObj->x.iVal = MemObjCharValue(&(*pObj));
|
||||
/* Invalidate any prior representations */
|
||||
SyBlobRelease(&pObj->sBlob);
|
||||
MemObjSetType(pObj, MEMOBJ_CHAR);
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
/*
|
||||
* Convert a ph7_value to type void.Invalidate any prior representations.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_MemObjToVoid(ph7_value *pObj) {
|
||||
if((pObj->iFlags & MEMOBJ_VOID) == 0) {
|
||||
PH7_MemObjRelease(pObj);
|
||||
MemObjSetType(pObj, MEMOBJ_VOID);
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 PH7_MemObjToCallback(ph7_value *pObj) {
|
||||
sxi32 rc = SXRET_OK;
|
||||
if((pObj->iFlags & (MEMOBJ_CALL | MEMOBJ_STRING)) == 0) {
|
||||
SyBlobReset(&pObj->sBlob); /* Reset the internal buffer */
|
||||
rc = MemObjStringValue(&pObj->sBlob, &(*pObj), TRUE);
|
||||
}
|
||||
MemObjSetType(pObj, MEMOBJ_CALL);
|
||||
return rc;
|
||||
}
|
||||
PH7_PRIVATE sxi32 PH7_MemObjToResource(ph7_value *pObj) {
|
||||
sxi32 rc = SXRET_OK;
|
||||
if((pObj->iFlags & MEMOBJ_NULL) == 0) {
|
||||
PH7_VmThrowError(&(*pObj->pVm), PH7_CTX_WARNING, "Unsafe type casting condition, assuming default value");
|
||||
}
|
||||
if((pObj->iFlags & MEMOBJ_RES) == 0) {
|
||||
pObj->x.iVal = 0;
|
||||
}
|
||||
MemObjSetType(pObj, MEMOBJ_RES);
|
||||
return rc;
|
||||
}
|
||||
/*
|
||||
* Convert a ph7_value to type string.Prior representations are NOT invalidated.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_MemObjToString(ph7_value *pObj) {
|
||||
sxi32 rc = SXRET_OK;
|
||||
if((pObj->iFlags & MEMOBJ_STRING) == 0) {
|
||||
if((pObj->iFlags & MEMOBJ_CALL) == 0) {
|
||||
/* Perform the conversion */
|
||||
SyBlobReset(&pObj->sBlob); /* Reset the internal buffer */
|
||||
rc = MemObjStringValue(&pObj->sBlob, &(*pObj), TRUE);
|
||||
}
|
||||
MemObjSetType(pObj, MEMOBJ_STRING);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
/*
|
||||
* Nullify a ph7_value.In other words invalidate any prior
|
||||
* representation.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_MemObjToNull(ph7_value *pObj) {
|
||||
return PH7_MemObjRelease(pObj);
|
||||
}
|
||||
/*
|
||||
* Convert a ph7_value to type array.Invalidate any prior representations.
|
||||
* According to the PHP language reference manual.
|
||||
|
@ -443,7 +604,12 @@ PH7_PRIVATE sxi32 PH7_MemObjToHashmap(ph7_value *pObj) {
|
|||
* Refer to the official documentation for more information.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_MemObjToObject(ph7_value *pObj) {
|
||||
if((pObj->iFlags & MEMOBJ_OBJ) == 0) {
|
||||
if(pObj->iFlags & MEMOBJ_NULL) {
|
||||
/* Invalidate any prior representation */
|
||||
PH7_MemObjRelease(pObj);
|
||||
/* Typecast the value */
|
||||
MemObjSetType(pObj, MEMOBJ_OBJ);
|
||||
} else if((pObj->iFlags & MEMOBJ_OBJ) == 0) {
|
||||
ph7_class_instance *pStd;
|
||||
ph7_class_method *pCons;
|
||||
ph7_class *pClass;
|
||||
|
@ -503,13 +669,19 @@ PH7_PRIVATE ProcMemObjCast PH7_MemObjCastMethod(sxi32 iFlags) {
|
|||
return PH7_MemObjToReal;
|
||||
} else if(iFlags & MEMOBJ_BOOL) {
|
||||
return PH7_MemObjToBool;
|
||||
} else if(iFlags & MEMOBJ_HASHMAP) {
|
||||
return PH7_MemObjToHashmap;
|
||||
} else if(iFlags & MEMOBJ_CHAR) {
|
||||
return PH7_MemObjToChar;
|
||||
} else if(iFlags & MEMOBJ_OBJ) {
|
||||
return PH7_MemObjToObject;
|
||||
} else if(iFlags & MEMOBJ_CALL) {
|
||||
return PH7_MemObjToCallback;
|
||||
} else if(iFlags & MEMOBJ_RES) {
|
||||
return PH7_MemObjToResource;
|
||||
} else if(iFlags & MEMOBJ_VOID) {
|
||||
return PH7_MemObjToVoid;
|
||||
}
|
||||
/* NULL cast */
|
||||
return PH7_MemObjToNull;
|
||||
/* Release the variable */
|
||||
return PH7_MemObjRelease;
|
||||
}
|
||||
/*
|
||||
* Check whether the ph7_value is numeric [i.e: int/float/bool] or looks
|
||||
|
@ -517,69 +689,10 @@ PH7_PRIVATE ProcMemObjCast PH7_MemObjCastMethod(sxi32 iFlags) {
|
|||
* Return TRUE if numeric.FALSE otherwise.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_MemObjIsNumeric(ph7_value *pObj) {
|
||||
if(pObj->iFlags & (MEMOBJ_BOOL | MEMOBJ_INT | MEMOBJ_REAL)) {
|
||||
if(pObj->iFlags & (MEMOBJ_INT | MEMOBJ_REAL)) {
|
||||
return TRUE;
|
||||
} else if(pObj->iFlags & (MEMOBJ_NULL | MEMOBJ_HASHMAP | MEMOBJ_OBJ | MEMOBJ_RES)) {
|
||||
}
|
||||
return FALSE;
|
||||
} else if(pObj->iFlags & MEMOBJ_STRING) {
|
||||
SyString sStr;
|
||||
sxi32 rc;
|
||||
SyStringInitFromBuf(&sStr, SyBlobData(&pObj->sBlob), SyBlobLength(&pObj->sBlob));
|
||||
if(sStr.nByte <= 0) {
|
||||
/* Empty string */
|
||||
return FALSE;
|
||||
}
|
||||
/* Check if the string representation looks like a numeric number */
|
||||
rc = SyStrIsNumeric(sStr.zString, sStr.nByte, 0, 0);
|
||||
return rc == SXRET_OK ? TRUE : FALSE;
|
||||
}
|
||||
/* NOT REACHED */
|
||||
return FALSE;
|
||||
}
|
||||
/*
|
||||
* Check whether the ph7_value is empty.Return TRUE if empty.
|
||||
* FALSE otherwise.
|
||||
* An ph7_value is considered empty if the following are true:
|
||||
* NULL value.
|
||||
* Boolean FALSE.
|
||||
* Integer/Float with a 0 (zero) value.
|
||||
* An empty string or a stream of 0 (zero) [i.e: "0","00","000",...].
|
||||
* An empty array.
|
||||
* NOTE
|
||||
* OBJECT VALUE MUST NOT BE MODIFIED.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_MemObjIsEmpty(ph7_value *pObj) {
|
||||
if(pObj->iFlags & MEMOBJ_NULL) {
|
||||
return TRUE;
|
||||
} else if(pObj->iFlags & MEMOBJ_INT) {
|
||||
return pObj->x.iVal == 0 ? TRUE : FALSE;
|
||||
} else if(pObj->iFlags & MEMOBJ_REAL) {
|
||||
return pObj->x.rVal == (ph7_real)0 ? TRUE : FALSE;
|
||||
} else if(pObj->iFlags & MEMOBJ_BOOL) {
|
||||
return !pObj->x.iVal;
|
||||
} else if(pObj->iFlags & MEMOBJ_STRING) {
|
||||
if(SyBlobLength(&pObj->sBlob) <= 0) {
|
||||
return TRUE;
|
||||
} else {
|
||||
const char *zIn, *zEnd;
|
||||
zIn = (const char *)SyBlobData(&pObj->sBlob);
|
||||
zEnd = &zIn[SyBlobLength(&pObj->sBlob)];
|
||||
while(zIn < zEnd) {
|
||||
if(zIn[0] != '0') {
|
||||
break;
|
||||
}
|
||||
zIn++;
|
||||
}
|
||||
return zIn >= zEnd ? TRUE : FALSE;
|
||||
}
|
||||
} else if(pObj->iFlags & MEMOBJ_HASHMAP) {
|
||||
ph7_hashmap *pMap = (ph7_hashmap *)pObj->x.pOther;
|
||||
return pMap->nEntry == 0 ? TRUE : FALSE;
|
||||
} else if(pObj->iFlags & (MEMOBJ_OBJ | MEMOBJ_RES)) {
|
||||
return FALSE;
|
||||
}
|
||||
/* Assume empty by default */
|
||||
return TRUE;
|
||||
}
|
||||
/*
|
||||
* Convert a ph7_value so that it has types MEMOBJ_REAL or MEMOBJ_INT
|
||||
|
@ -591,8 +704,8 @@ PH7_PRIVATE sxi32 PH7_MemObjIsEmpty(ph7_value *pObj) {
|
|||
*/
|
||||
PH7_PRIVATE sxi32 PH7_MemObjToNumeric(ph7_value *pObj) {
|
||||
if(pObj->iFlags & (MEMOBJ_INT | MEMOBJ_REAL | MEMOBJ_BOOL | MEMOBJ_NULL)) {
|
||||
if(pObj->iFlags & (MEMOBJ_BOOL | MEMOBJ_NULL)) {
|
||||
if(pObj->iFlags & MEMOBJ_NULL) {
|
||||
if(pObj->iFlags & (MEMOBJ_BOOL | MEMOBJ_NULL | MEMOBJ_VOID)) {
|
||||
if(pObj->iFlags & (MEMOBJ_CALL | MEMOBJ_NULL | MEMOBJ_VOID)) {
|
||||
pObj->x.iVal = 0;
|
||||
}
|
||||
MemObjSetType(pObj, MEMOBJ_INT);
|
||||
|
@ -686,6 +799,18 @@ PH7_PRIVATE sxi32 PH7_MemObjInitFromReal(ph7_vm *pVm, ph7_value *pObj, ph7_real
|
|||
return SXRET_OK;
|
||||
}
|
||||
/*
|
||||
* Initialize a ph7_value to the void type.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_MemObjInitFromVoid(ph7_vm *pVm, ph7_value *pObj, ph7_real rVal) {
|
||||
/* Zero the structure */
|
||||
SyZero(pObj, sizeof(ph7_value));
|
||||
/* Initialize fields */
|
||||
pObj->pVm = pVm;
|
||||
SyBlobInit(&pObj->sBlob, &pVm->sAllocator);
|
||||
/* Set the desired type */
|
||||
pObj->iFlags = MEMOBJ_VOID;
|
||||
return SXRET_OK;
|
||||
}/*
|
||||
* Initialize a ph7_value to the array type.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_MemObjInitFromArray(ph7_vm *pVm, ph7_value *pObj, ph7_hashmap *pArray) {
|
||||
|
@ -757,6 +882,7 @@ PH7_PRIVATE sxi32 PH7_MemObjStore(ph7_value *pSrc, ph7_value *pDest) {
|
|||
ph7_class_instance *pObj = 0;
|
||||
ph7_hashmap *pMap = 0;
|
||||
sxi32 rc;
|
||||
if(pSrc->x.pOther) {
|
||||
if(pSrc->iFlags & MEMOBJ_HASHMAP) {
|
||||
/* Increment reference count */
|
||||
((ph7_hashmap *)pSrc->x.pOther)->iRef++;
|
||||
|
@ -764,13 +890,13 @@ PH7_PRIVATE sxi32 PH7_MemObjStore(ph7_value *pSrc, ph7_value *pDest) {
|
|||
/* Increment reference count */
|
||||
((ph7_class_instance *)pSrc->x.pOther)->iRef++;
|
||||
}
|
||||
}
|
||||
if(pDest->iFlags & MEMOBJ_HASHMAP) {
|
||||
pMap = (ph7_hashmap *)pDest->x.pOther;
|
||||
} else if(pDest->iFlags & MEMOBJ_OBJ) {
|
||||
pObj = (ph7_class_instance *)pDest->x.pOther;
|
||||
}
|
||||
SyMemcpy((const void *) & (*pSrc), &(*pDest), sizeof(ph7_value) - (sizeof(ph7_vm *) + sizeof(SyBlob) + sizeof(sxu32)));
|
||||
pDest->iFlags &= ~MEMOBJ_AUX;
|
||||
rc = SXRET_OK;
|
||||
if(SyBlobLength(&pSrc->sBlob) > 0) {
|
||||
SyBlobReset(&pDest->sBlob);
|
||||
|
@ -794,6 +920,7 @@ PH7_PRIVATE sxi32 PH7_MemObjStore(ph7_value *pSrc, ph7_value *pDest) {
|
|||
PH7_PRIVATE sxi32 PH7_MemObjLoad(ph7_value *pSrc, ph7_value *pDest) {
|
||||
SyMemcpy((const void *) & (*pSrc), &(*pDest),
|
||||
sizeof(ph7_value) - (sizeof(ph7_vm *) + sizeof(SyBlob) + sizeof(sxu32)));
|
||||
if(pSrc->x.pOther) {
|
||||
if(pSrc->iFlags & MEMOBJ_HASHMAP) {
|
||||
/* Increment reference count */
|
||||
((ph7_hashmap *)pSrc->x.pOther)->iRef++;
|
||||
|
@ -801,6 +928,7 @@ PH7_PRIVATE sxi32 PH7_MemObjLoad(ph7_value *pSrc, ph7_value *pDest) {
|
|||
/* Increment reference count */
|
||||
((ph7_class_instance *)pSrc->x.pOther)->iRef++;
|
||||
}
|
||||
}
|
||||
if(SyBlobLength(&pDest->sBlob) > 0) {
|
||||
SyBlobRelease(&pDest->sBlob);
|
||||
}
|
||||
|
@ -814,11 +942,13 @@ PH7_PRIVATE sxi32 PH7_MemObjLoad(ph7_value *pSrc, ph7_value *pDest) {
|
|||
*/
|
||||
PH7_PRIVATE sxi32 PH7_MemObjRelease(ph7_value *pObj) {
|
||||
if((pObj->iFlags & MEMOBJ_NULL) == 0) {
|
||||
if(pObj->x.pOther) {
|
||||
if(pObj->iFlags & MEMOBJ_HASHMAP) {
|
||||
PH7_HashmapUnref((ph7_hashmap *)pObj->x.pOther);
|
||||
} else if(pObj->iFlags & MEMOBJ_OBJ) {
|
||||
PH7_ClassInstanceUnref((ph7_class_instance *)pObj->x.pOther);
|
||||
}
|
||||
}
|
||||
/* Release the internal buffer */
|
||||
SyBlobRelease(&pObj->sBlob);
|
||||
/* Invalidate any prior representation */
|
||||
|
@ -885,8 +1015,8 @@ PH7_PRIVATE sxi32 PH7_MemObjCmp(ph7_value *pObj1, ph7_value *pObj2, int bStrict,
|
|||
if(bStrict) {
|
||||
sxi32 iF1, iF2;
|
||||
/* Strict comparisons with === */
|
||||
iF1 = pObj1->iFlags & ~MEMOBJ_AUX;
|
||||
iF2 = pObj2->iFlags & ~MEMOBJ_AUX;
|
||||
iF1 = pObj1->iFlags;
|
||||
iF2 = pObj2->iFlags;
|
||||
if(iF1 != iF2) {
|
||||
/* Not of the same type */
|
||||
return 1;
|
||||
|
@ -978,10 +1108,6 @@ Numeric:
|
|||
PH7_MemObjToNumeric(pObj2);
|
||||
}
|
||||
if((pObj1->iFlags & pObj2->iFlags & MEMOBJ_INT) == 0) {
|
||||
/*
|
||||
* Symisc eXtension to the PHP language:
|
||||
* Floating point comparison is introduced and works as expected.
|
||||
*/
|
||||
ph7_real r1, r2;
|
||||
/* Compare as reals */
|
||||
if((pObj1->iFlags & MEMOBJ_REAL) == 0) {
|
||||
|
@ -1061,7 +1187,6 @@ PH7_PRIVATE sxi32 PH7_MemObjAdd(ph7_value *pObj1, ph7_value *pObj2, int bAddStor
|
|||
rc = PH7_MemObjToHashmap(pObj1);
|
||||
if(rc != SXRET_OK) {
|
||||
PH7_VmMemoryError(pObj1->pVm);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
/* Point to the structure that describe the hashmap */
|
||||
|
@ -1071,7 +1196,6 @@ PH7_PRIVATE sxi32 PH7_MemObjAdd(ph7_value *pObj1, ph7_value *pObj2, int bAddStor
|
|||
pMap = PH7_NewHashmap(pObj1->pVm, 0, 0);
|
||||
if(pMap == 0) {
|
||||
PH7_VmMemoryError(pObj1->pVm);
|
||||
return SXERR_MEM;
|
||||
}
|
||||
}
|
||||
if(!bAddStore) {
|
||||
|
@ -1111,7 +1235,32 @@ PH7_PRIVATE sxi32 PH7_MemObjAdd(ph7_value *pObj1, ph7_value *pObj2, int bAddStor
|
|||
PH7_PRIVATE const char *PH7_MemObjTypeDump(ph7_value *pVal) {
|
||||
const char *zType = "";
|
||||
if(pVal->iFlags & MEMOBJ_NULL) {
|
||||
zType = "null";
|
||||
zType = "NULL";
|
||||
} else {
|
||||
if(pVal->iFlags & MEMOBJ_HASHMAP) {
|
||||
if(pVal->iFlags & MEMOBJ_MIXED) {
|
||||
zType = "array(mixed, ";
|
||||
} else if(pVal->iFlags & MEMOBJ_OBJ) {
|
||||
zType = "array(object, ";
|
||||
} else if(pVal->iFlags & MEMOBJ_INT) {
|
||||
zType = "array(int, ";
|
||||
} else if(pVal->iFlags & MEMOBJ_REAL) {
|
||||
zType = "array(float, ";
|
||||
} else if(pVal->iFlags & MEMOBJ_STRING) {
|
||||
zType = "array(string, ";
|
||||
} else if(pVal->iFlags & MEMOBJ_BOOL) {
|
||||
zType = "array(bool, ";
|
||||
} else if(pVal->iFlags & MEMOBJ_CHAR) {
|
||||
zType = "array(char, ";
|
||||
} else if(pVal->iFlags & MEMOBJ_RES) {
|
||||
zType = "array(resource, ";
|
||||
} else if(pVal->iFlags & MEMOBJ_CALL) {
|
||||
zType = "array(callback, ";
|
||||
} else if(pVal->iFlags & MEMOBJ_VOID) {
|
||||
zType = "array(void, ";
|
||||
}
|
||||
} else if(pVal->iFlags & MEMOBJ_OBJ) {
|
||||
zType = "object";
|
||||
} else if(pVal->iFlags & MEMOBJ_INT) {
|
||||
zType = "int";
|
||||
} else if(pVal->iFlags & MEMOBJ_REAL) {
|
||||
|
@ -1120,12 +1269,15 @@ PH7_PRIVATE const char *PH7_MemObjTypeDump(ph7_value *pVal) {
|
|||
zType = "string";
|
||||
} else if(pVal->iFlags & MEMOBJ_BOOL) {
|
||||
zType = "bool";
|
||||
} else if(pVal->iFlags & MEMOBJ_HASHMAP) {
|
||||
zType = "array";
|
||||
} else if(pVal->iFlags & MEMOBJ_OBJ) {
|
||||
zType = "object";
|
||||
} else if(pVal->iFlags & MEMOBJ_CHAR) {
|
||||
zType = "char";
|
||||
} else if(pVal->iFlags & MEMOBJ_RES) {
|
||||
zType = "resource";
|
||||
} else if(pVal->iFlags & MEMOBJ_CALL) {
|
||||
zType = "callback";
|
||||
} else if(pVal->iFlags & MEMOBJ_VOID) {
|
||||
zType = "void";
|
||||
}
|
||||
}
|
||||
return zType;
|
||||
}
|
||||
|
@ -1138,8 +1290,7 @@ PH7_PRIVATE sxi32 PH7_MemObjDump(
|
|||
ph7_value *pObj, /* Dump this */
|
||||
int ShowType, /* TRUE to output value type */
|
||||
int nTab, /* # of Whitespace to insert */
|
||||
int nDepth, /* Nesting level */
|
||||
int isRef /* TRUE if referenced object */
|
||||
int nDepth /* Nesting level */
|
||||
) {
|
||||
sxi32 rc = SXRET_OK;
|
||||
const char *zType;
|
||||
|
@ -1148,15 +1299,12 @@ PH7_PRIVATE sxi32 PH7_MemObjDump(
|
|||
SyBlobAppend(&(*pOut), " ", sizeof(char));
|
||||
}
|
||||
if(ShowType) {
|
||||
if(isRef) {
|
||||
SyBlobAppend(&(*pOut), "&", sizeof(char));
|
||||
}
|
||||
/* Get value type first */
|
||||
zType = PH7_MemObjTypeDump(pObj);
|
||||
SyBlobAppend(&(*pOut), zType, SyStrlen(zType));
|
||||
}
|
||||
if((pObj->iFlags & MEMOBJ_NULL) == 0) {
|
||||
if(ShowType) {
|
||||
if(ShowType && (pObj->iFlags & MEMOBJ_HASHMAP) == 0) {
|
||||
SyBlobAppend(&(*pOut), "(", sizeof(char));
|
||||
}
|
||||
if(pObj->iFlags & MEMOBJ_HASHMAP) {
|
||||
|
@ -1165,10 +1313,12 @@ PH7_PRIVATE sxi32 PH7_MemObjDump(
|
|||
} else if(pObj->iFlags & MEMOBJ_OBJ) {
|
||||
/* Dump class instance attributes */
|
||||
rc = PH7_ClassInstanceDump(&(*pOut), (ph7_class_instance *)pObj->x.pOther, ShowType, nTab + 1, nDepth + 1);
|
||||
} else if(pObj->iFlags & MEMOBJ_VOID) {
|
||||
SyBlobAppend(&(*pOut), "NULL", sizeof("NULL") - 1);
|
||||
} else {
|
||||
SyBlob *pContents = &pObj->sBlob;
|
||||
/* Get a printable representation of the contents */
|
||||
if((pObj->iFlags & MEMOBJ_STRING) == 0) {
|
||||
if((pObj->iFlags & (MEMOBJ_STRING | MEMOBJ_CALL)) == 0) {
|
||||
MemObjStringValue(&(*pOut), &(*pObj), FALSE);
|
||||
} else {
|
||||
/* Append length first */
|
||||
|
|
32
engine/oop.c
32
engine/oop.c
|
@ -75,7 +75,7 @@ PH7_PRIVATE ph7_class *PH7_NewRawClass(ph7_vm *pVm, const SyString *pName) {
|
|||
* Allocate and initialize a new class attribute.
|
||||
* Return a pointer to the class attribute on success. NULL otherwise.
|
||||
*/
|
||||
PH7_PRIVATE ph7_class_attr *PH7_NewClassAttr(ph7_vm *pVm, const SyString *pName, sxu32 nLine, sxi32 iProtection, sxi32 iFlags) {
|
||||
PH7_PRIVATE ph7_class_attr *PH7_NewClassAttr(ph7_vm *pVm, const SyString *pName, sxu32 nLine, sxi32 iProtection, sxi32 iFlags, sxu32 nType) {
|
||||
ph7_class_attr *pAttr;
|
||||
char *zName;
|
||||
pAttr = (ph7_class_attr *)SyMemBackendPoolAlloc(&pVm->sAllocator, sizeof(ph7_class_attr));
|
||||
|
@ -96,6 +96,7 @@ PH7_PRIVATE ph7_class_attr *PH7_NewClassAttr(ph7_vm *pVm, const SyString *pName,
|
|||
pAttr->iProtection = iProtection;
|
||||
pAttr->nIdx = SXU32_HIGH;
|
||||
pAttr->iFlags = iFlags;
|
||||
pAttr->nType = nType;
|
||||
pAttr->nLine = nLine;
|
||||
return pAttr;
|
||||
}
|
||||
|
@ -383,7 +384,8 @@ PH7_PRIVATE sxi32 PH7_ClassInterfaceInherit(ph7_class *pSub, ph7_class *pBase) {
|
|||
* Any other return value indicates failure and the upper layer must generate an appropriate
|
||||
* error message.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_ClassImplement(ph7_class *pMain, ph7_class *pInterface) {
|
||||
PH7_PRIVATE sxi32 PH7_ClassImplement(ph7_vm *pVm, ph7_class *pMain, ph7_class *pInterface) {
|
||||
ph7_class_method *pMeth;
|
||||
ph7_class_attr *pAttr;
|
||||
SyHashEntry *pEntry;
|
||||
SyString *pName;
|
||||
|
@ -403,12 +405,22 @@ PH7_PRIVATE sxi32 PH7_ClassImplement(ph7_class *pMain, ph7_class *pInterface) {
|
|||
}
|
||||
}
|
||||
}
|
||||
SyHashResetLoopCursor(&pInterface->hMethod);
|
||||
while((pEntry = SyHashGetNextEntry(&pInterface->hMethod)) != 0) {
|
||||
pMeth = (ph7_class_method *)pEntry->pUserData;
|
||||
pName = &pMeth->sFunc.sName;
|
||||
if((pEntry = SyHashGet(&pMain->hMethod, (const void *)pName->zString, pName->nByte)) != 0) {
|
||||
continue;
|
||||
} else {
|
||||
rc = PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Method '%z:%z()' must be defined inside class '%z'", &pInterface->sName, pName, &pMain->sName);
|
||||
if(rc == SXERR_ABORT) {
|
||||
return SXERR_ABORT;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* Install in the interface container */
|
||||
SySetPut(&pMain->aInterface, (const void *)&pInterface);
|
||||
/* TICKET 1433-49/1: Symisc eXtension
|
||||
* A class may not implement all declared interface methods,so there
|
||||
* is no need for a method installer loop here.
|
||||
*/
|
||||
return SXRET_OK;
|
||||
}
|
||||
/*
|
||||
|
@ -717,12 +729,14 @@ static void PH7_ClassInstanceRelease(ph7_class_instance *pThis) {
|
|||
* If the reference count reaches zero,release the whole instance.
|
||||
*/
|
||||
PH7_PRIVATE void PH7_ClassInstanceUnref(ph7_class_instance *pThis) {
|
||||
if(pThis) {
|
||||
pThis->iRef--;
|
||||
if(pThis->iRef < 1) {
|
||||
/* No more reference to this instance */
|
||||
PH7_ClassInstanceRelease(&(*pThis));
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Compare two class instances [i.e: Objects in the PHP jargon]
|
||||
* Note on objects comparison:
|
||||
|
@ -890,6 +904,7 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceDump(SyBlob *pOut, ph7_class_instance *pThis,
|
|||
if(!ShowType) {
|
||||
SyBlobAppend(&(*pOut), "Object(", sizeof("Object(") - 1);
|
||||
}
|
||||
if(pThis) {
|
||||
/* Append class name */
|
||||
SyBlobFormat(&(*pOut), "%z) {", &pThis->pClass->sName);
|
||||
#ifdef __WINNT__
|
||||
|
@ -914,7 +929,7 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceDump(SyBlob *pOut, ph7_class_instance *pThis,
|
|||
#else
|
||||
SyBlobAppend(&(*pOut), "\n", sizeof(char));
|
||||
#endif
|
||||
rc = PH7_MemObjDump(&(*pOut), pValue, ShowType, nTab + 1, nDepth, 0);
|
||||
rc = PH7_MemObjDump(&(*pOut), pValue, ShowType, nTab + 1, nDepth);
|
||||
if(rc == SXERR_LIMIT) {
|
||||
break;
|
||||
}
|
||||
|
@ -925,6 +940,9 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceDump(SyBlob *pOut, ph7_class_instance *pThis,
|
|||
SyBlobAppend(&(*pOut), " ", sizeof(char));
|
||||
}
|
||||
SyBlobAppend(&(*pOut), "}", sizeof(char));
|
||||
} else {
|
||||
SyBlobAppend(&(*pOut), ")", sizeof(char));
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
/*
|
||||
|
|
|
@ -174,15 +174,16 @@ static const ph7_expr_op aOpTable[] = {
|
|||
{ {"+", sizeof(char)}, EXPR_OP_UPLUS, 4, EXPR_OP_ASSOC_RIGHT, PH7_OP_UPLUS },
|
||||
{ {"~", sizeof(char)}, EXPR_OP_BITNOT, 4, EXPR_OP_ASSOC_RIGHT, PH7_OP_BITNOT },
|
||||
{ {"!", sizeof(char)}, EXPR_OP_LOGNOT, 4, EXPR_OP_ASSOC_RIGHT, PH7_OP_LNOT },
|
||||
{ {"@", sizeof(char)}, EXPR_OP_ALT, 4, EXPR_OP_ASSOC_RIGHT, PH7_OP_ERR_CTRL},
|
||||
/* Cast operators */
|
||||
{ {"(int)", sizeof("(int)") - 1 }, EXPR_OP_TYPECAST, 4, EXPR_OP_ASSOC_RIGHT, PH7_OP_CVT_INT },
|
||||
{ {"(bool)", sizeof("(bool)") - 1 }, EXPR_OP_TYPECAST, 4, EXPR_OP_ASSOC_RIGHT, PH7_OP_CVT_BOOL },
|
||||
{ {"(char)", sizeof("(char)") - 1 }, EXPR_OP_TYPECAST, 4, EXPR_OP_ASSOC_RIGHT, PH7_OP_CVT_CHAR },
|
||||
{ {"(string)", sizeof("(string)") - 1}, EXPR_OP_TYPECAST, 4, EXPR_OP_ASSOC_RIGHT, PH7_OP_CVT_STR },
|
||||
{ {"(float)", sizeof("(float)") - 1 }, EXPR_OP_TYPECAST, 4, EXPR_OP_ASSOC_RIGHT, PH7_OP_CVT_REAL },
|
||||
{ {"(array)", sizeof("(array)") - 1 }, EXPR_OP_TYPECAST, 4, EXPR_OP_ASSOC_RIGHT, PH7_OP_CVT_ARRAY},
|
||||
{ {"(object)", sizeof("(object)") - 1}, EXPR_OP_TYPECAST, 4, EXPR_OP_ASSOC_RIGHT, PH7_OP_CVT_OBJ },
|
||||
{ {"(unset)", sizeof("(unset)") - 1 }, EXPR_OP_TYPECAST, 4, EXPR_OP_ASSOC_RIGHT, PH7_OP_CVT_NULL },
|
||||
{ {"(callback)", sizeof("(callback)") - 1}, EXPR_OP_TYPECAST, 4, EXPR_OP_ASSOC_RIGHT, PH7_OP_CVT_CALL},
|
||||
{ {"(resource)", sizeof("(resource)") - 1}, EXPR_OP_TYPECAST, 4, EXPR_OP_ASSOC_RIGHT, PH7_OP_CVT_RES},
|
||||
{ {"(void)", sizeof("(void)") - 1 }, EXPR_OP_TYPECAST, 4, EXPR_OP_ASSOC_RIGHT, PH7_OP_CVT_VOID },
|
||||
/* Binary operators */
|
||||
/* Precedence 7,left-associative */
|
||||
{ {"instanceof", sizeof("instanceof") - 1}, EXPR_OP_INSTOF, 7, EXPR_OP_NON_ASSOC, PH7_OP_IS_A},
|
||||
|
@ -204,12 +205,8 @@ static const ph7_expr_op aOpTable[] = {
|
|||
/* Precedence 11,non-associative */
|
||||
{ {"==", sizeof(char) * 2}, EXPR_OP_EQ, 11, EXPR_OP_NON_ASSOC, PH7_OP_EQ},
|
||||
{ {"!=", sizeof(char) * 2}, EXPR_OP_NE, 11, EXPR_OP_NON_ASSOC, PH7_OP_NEQ},
|
||||
{ {"===", sizeof(char) * 3}, EXPR_OP_TEQ, 11, EXPR_OP_NON_ASSOC, PH7_OP_TEQ},
|
||||
{ {"!==", sizeof(char) * 3}, EXPR_OP_TNE, 11, EXPR_OP_NON_ASSOC, PH7_OP_TNE},
|
||||
/* Precedence 12,left-associative */
|
||||
{ {"&", sizeof(char)}, EXPR_OP_BAND, 12, EXPR_OP_ASSOC_LEFT, PH7_OP_BAND},
|
||||
/* Precedence 12,left-associative */
|
||||
{ {"=&", sizeof(char) * 2}, EXPR_OP_REF, 12, EXPR_OP_ASSOC_LEFT, PH7_OP_STORE_REF},
|
||||
/* Binary operators */
|
||||
/* Precedence 13,left-associative */
|
||||
{ {"^", sizeof(char)}, EXPR_OP_XOR, 13, EXPR_OP_ASSOC_LEFT, PH7_OP_BXOR},
|
||||
|
@ -367,7 +364,7 @@ static sxi32 ExprVerifyNodes(ph7_gen_state *pGen, ph7_expr_node **apNode, sxi32
|
|||
return rc;
|
||||
}
|
||||
iSquare--;
|
||||
} else if(apNode[i]->pStart->nType & PH7_TK_OCB /*'{'*/) {
|
||||
} else if(apNode[i]->pStart->nType & PH7_TK_OCB /*'{'*/ && apNode[i]->xCode != PH7_CompileArray) {
|
||||
iBraces++;
|
||||
if(i > 0 && (apNode[i - 1]->xCode == PH7_CompileVariable || (apNode[i - 1]->pStart->nType & PH7_TK_CSB/*]*/))) {
|
||||
const ph7_expr_op *pOp, *pEnd;
|
||||
|
@ -608,7 +605,7 @@ Synchronize:
|
|||
* An expression node can be a variable [i.e: $var],an operator [i.e: ++]
|
||||
* an anonymous function [i.e: function(){ return "Hello"; }, a double/single
|
||||
* quoted string, a literal [i.e: PHP_EOL],a namespace path
|
||||
* [i.e: namespaces\path\to..],a array/list [i.e: array(4,5,6)] and so on.
|
||||
* [i.e: namespaces\path\to..],an array [i.e: {4,5,6}] and so on.
|
||||
*/
|
||||
static sxi32 ExprExtractNode(ph7_gen_state *pGen, ph7_expr_node **ppNode) {
|
||||
ph7_expr_node *pNode;
|
||||
|
@ -659,45 +656,25 @@ static sxi32 ExprExtractNode(ph7_gen_state *pGen, ph7_expr_node **ppNode) {
|
|||
}
|
||||
}
|
||||
pNode->xCode = PH7_CompileVariable;
|
||||
} else if(pCur->nType & PH7_TK_KEYWORD) {
|
||||
sxu32 nKeyword = (sxu32)SX_PTR_TO_INT(pCur->pUserData);
|
||||
if(nKeyword == PH7_KEYWORD_ARRAY || nKeyword == PH7_KEYWORD_LIST) {
|
||||
/* List/Array node */
|
||||
if(&pCur[1] >= pGen->pEnd || (pCur[1].nType & PH7_TK_LPAREN) == 0) {
|
||||
/* Assume a literal */
|
||||
ExprAssembleLiteral(&pCur, pGen->pEnd);
|
||||
pNode->xCode = PH7_CompileLiteral;
|
||||
} else {
|
||||
pCur += 2;
|
||||
/* Collect array/list tokens */
|
||||
PH7_DelimitNestedTokens(pCur, pGen->pEnd, PH7_TK_LPAREN /* '(' */, PH7_TK_RPAREN /* ')' */, &pCur);
|
||||
} else if(pCur->nType & PH7_TK_OCB /* '{' */) {
|
||||
/* Array, assemble tokens */
|
||||
pCur++;
|
||||
PH7_DelimitNestedTokens(pCur, pGen->pEnd, PH7_TK_OCB /* '{' */, PH7_TK_CCB /* '}' */, &pCur);
|
||||
if(pCur < pGen->pEnd) {
|
||||
pCur++;
|
||||
} else {
|
||||
/* Syntax error */
|
||||
rc = PH7_GenCompileError(pGen, E_ERROR, pNode->pStart->nLine,
|
||||
"%s: Missing closing parenthesis ')'", nKeyword == PH7_KEYWORD_LIST ? "list" : "array");
|
||||
rc = PH7_GenCompileError(pGen, E_ERROR, pNode->pStart->nLine, "Syntax error: Missing closing braces '}'");
|
||||
if(rc != SXERR_ABORT) {
|
||||
rc = SXERR_SYNTAX;
|
||||
}
|
||||
SyMemBackendPoolFree(&pGen->pVm->sAllocator, pNode);
|
||||
return rc;
|
||||
}
|
||||
pNode->xCode = (nKeyword == PH7_KEYWORD_LIST) ? PH7_CompileList : PH7_CompileArray;
|
||||
if(pNode->xCode == PH7_CompileList) {
|
||||
ph7_expr_op *pOp = (pCur < pGen->pEnd) ? (ph7_expr_op *)pCur->pUserData : 0;
|
||||
if(pCur >= pGen->pEnd || (pCur->nType & PH7_TK_OP) == 0 || pOp == 0 || pOp->iVmOp != PH7_OP_STORE /*'='*/) {
|
||||
/* Syntax error */
|
||||
rc = PH7_GenCompileError(pGen, E_ERROR, pNode->pStart->nLine, "list(): expecting '=' after construct");
|
||||
if(rc != SXERR_ABORT) {
|
||||
rc = SXERR_SYNTAX;
|
||||
}
|
||||
SyMemBackendPoolFree(&pGen->pVm->sAllocator, pNode);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(nKeyword == PH7_KEYWORD_FUNCTION) {
|
||||
pNode->xCode = PH7_CompileArray;
|
||||
} else if(pCur->nType & PH7_TK_KEYWORD) {
|
||||
sxu32 nKeyword = (sxu32)SX_PTR_TO_INT(pCur->pUserData);
|
||||
if(pCur[1].nType & PH7_TK_LPAREN && (nKeyword & PH7_KEYWORD_TYPEDEF)) {
|
||||
/* Anonymous function */
|
||||
if(&pCur[1] >= pGen->pEnd) {
|
||||
/* Assume a literal */
|
||||
|
@ -878,13 +855,6 @@ static sxi32 ExprProcessFuncArguments(ph7_gen_state *pGen, ph7_expr_node *pOp, p
|
|||
iCur++;
|
||||
}
|
||||
if(iCur > iNode) {
|
||||
if(apNode[iNode] && (apNode[iNode]->pStart->nType & PH7_TK_AMPER /*'&'*/) && ((iCur - iNode) == 2)
|
||||
&& apNode[iNode + 1]->xCode == PH7_CompileVariable) {
|
||||
PH7_GenCompileError(&(*pGen), E_WARNING, apNode[iNode]->pStart->nLine,
|
||||
"call-time pass-by-reference is deprecated");
|
||||
ExprFreeTree(&(*pGen), apNode[iNode]);
|
||||
apNode[iNode] = 0;
|
||||
}
|
||||
ExprMakeTree(&(*pGen), &apNode[iNode], iCur - iNode);
|
||||
if(apNode[iNode]) {
|
||||
/* Put a pointer to the root of the tree in the arguments set */
|
||||
|
@ -980,7 +950,7 @@ static sxi32 ExprMakeTree(ph7_gen_state *pGen, ph7_expr_node **apNode, sxi32 nTo
|
|||
/* Note that, we use strict comparison here '!=' instead of the bitwise and '&' operator
|
||||
* since the OCB '{' token can also be an operator [i.e: subscripting].
|
||||
*/
|
||||
if(apNode[iCur] == 0 || apNode[iCur]->pStart->nType != PH7_TK_OCB) {
|
||||
if(apNode[iCur] == 0 || apNode[iCur]->pStart->nType != PH7_TK_OCB || apNode[iCur]->xCode == PH7_CompileArray) {
|
||||
continue;
|
||||
}
|
||||
iNest = 1;
|
||||
|
@ -1449,7 +1419,7 @@ static sxi32 ExprMakeTree(ph7_gen_state *pGen, ph7_expr_node **apNode, sxi32 nTo
|
|||
return rc;
|
||||
}
|
||||
if(ExprIsModifiableValue(apNode[iLeft], FALSE) == FALSE) {
|
||||
if(pNode->pOp->iVmOp != PH7_OP_STORE || apNode[iLeft]->xCode != PH7_CompileList) {
|
||||
if(pNode->pOp->iVmOp == PH7_OP_STORE) {
|
||||
/* Left operand must be a modifiable l-value */
|
||||
rc = PH7_GenCompileError(pGen, E_ERROR, pNode->pStart->nLine,
|
||||
"'%z': Left operand must be a modifiable l-value", &pNode->pOp->sOp);
|
||||
|
|
28
engine/vfs.c
28
engine/vfs.c
|
@ -1255,8 +1255,6 @@ static int PH7_vfs_stat(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||
pValue = ph7_context_new_scalar(pCtx);
|
||||
if(pArray == 0 || pValue == 0) {
|
||||
PH7_VmMemoryError(pCtx->pVm);
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Extract the file path */
|
||||
zPath = ph7_value_to_string(apArg[0], 0);
|
||||
|
@ -1323,8 +1321,6 @@ static int PH7_vfs_lstat(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||
pValue = ph7_context_new_scalar(pCtx);
|
||||
if(pArray == 0 || pValue == 0) {
|
||||
PH7_VmMemoryError(pCtx->pVm);
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Extract the file path */
|
||||
zPath = ph7_value_to_string(apArg[0], 0);
|
||||
|
@ -3250,8 +3246,6 @@ static int PH7_builtin_fread(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||
pBuf = ph7_context_alloc_chunk(pCtx, (unsigned int)nLen, FALSE, FALSE);
|
||||
if(pBuf == 0) {
|
||||
PH7_VmMemoryError(pCtx->pVm);
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Perform the requested operation */
|
||||
nRead = StreamRead(pDev, pBuf, (ph7_int64)nLen);
|
||||
|
@ -3367,8 +3361,6 @@ static int PH7_builtin_fgetcsv(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||
pArray = ph7_context_new_array(pCtx);
|
||||
if(pArray == 0) {
|
||||
PH7_VmMemoryError(pCtx->pVm);
|
||||
ph7_result_null(pCtx);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Parse the raw input */
|
||||
PH7_ProcessCsv(zLine, (int)n, delim, encl, escape, PH7_CsvConsumer, pArray);
|
||||
|
@ -3462,7 +3454,7 @@ static int PH7_builtin_readdir(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
|
||||
/* Missing/Invalid arguments,return FALSE */
|
||||
PH7_VmThrowError(pCtx->pVm, PH7_CTX_WARNING, "Expecting an IO handle");
|
||||
ph7_result_bool(pCtx, 0);
|
||||
ph7_result_string(pCtx, "", 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Extract our private data */
|
||||
|
@ -3471,7 +3463,7 @@ static int PH7_builtin_readdir(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||
if(IO_PRIVATE_INVALID(pDev)) {
|
||||
/*Expecting an IO handle */
|
||||
PH7_VmThrowError(pCtx->pVm, PH7_CTX_WARNING, "Expecting an IO handle");
|
||||
ph7_result_bool(pCtx, 0);
|
||||
ph7_result_string(pCtx, "", 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Point to the target IO stream device */
|
||||
|
@ -3481,7 +3473,7 @@ static int PH7_builtin_readdir(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||
"IO routine(%s) not implemented in the underlying stream(%s) device",
|
||||
ph7_function_name(pCtx), pStream ? pStream->zName : "null_stream"
|
||||
);
|
||||
ph7_result_bool(pCtx, 0);
|
||||
ph7_result_string(pCtx, "", 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
ph7_result_bool(pCtx, 0);
|
||||
|
@ -3489,7 +3481,7 @@ static int PH7_builtin_readdir(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||
rc = pStream->xReadDir(pDev->pHandle, pCtx);
|
||||
if(rc != PH7_OK) {
|
||||
/* Return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
ph7_result_string(pCtx, "", 0);
|
||||
}
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -3625,8 +3617,6 @@ static int PH7_builtin_opendir(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||
pDev = (io_private *)ph7_context_alloc_chunk(pCtx, sizeof(io_private), TRUE, FALSE);
|
||||
if(pDev == 0) {
|
||||
PH7_VmMemoryError(pCtx->pVm);
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Initialize the structure */
|
||||
InitIOPrivate(pCtx->pVm, pStream, pDev);
|
||||
|
@ -3956,8 +3946,6 @@ static int PH7_builtin_file(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||
pDev = (io_private *)ph7_context_alloc_chunk(pCtx, sizeof(io_private), TRUE, FALSE);
|
||||
if(pDev == 0) {
|
||||
PH7_VmMemoryError(pCtx->pVm);
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Initialize the structure */
|
||||
InitIOPrivate(pCtx->pVm, pStream, pDev);
|
||||
|
@ -3973,8 +3961,6 @@ static int PH7_builtin_file(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||
pLine = ph7_context_new_scalar(pCtx);
|
||||
if(pArray == 0 || pLine == 0) {
|
||||
PH7_VmMemoryError(pCtx->pVm);
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Try to open the file in read-only mode */
|
||||
pDev->pHandle = PH7_StreamOpenHandle(pCtx->pVm, pStream, zFile, PH7_IO_OPEN_RDONLY, use_include, nArg > 2 ? apArg[2] : 0, FALSE, 0);
|
||||
|
@ -4168,8 +4154,6 @@ static int PH7_builtin_fstat(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||
pValue = ph7_context_new_scalar(pCtx);
|
||||
if(pArray == 0 || pValue == 0) {
|
||||
PH7_VmMemoryError(pCtx->pVm);
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Perform the requested operation */
|
||||
pStream->xStat(pDev->pHandle, pArray, pValue);
|
||||
|
@ -4848,8 +4832,6 @@ static int PH7_builtin_fopen(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||
pDev = (io_private *)ph7_context_alloc_chunk(pCtx, sizeof(io_private), TRUE, FALSE);
|
||||
if(pDev == 0) {
|
||||
PH7_VmMemoryError(pCtx->pVm);
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
pResource = 0;
|
||||
if(nArg > 3) {
|
||||
|
@ -5202,8 +5184,6 @@ static int PH7_builtin_zip_open(ph7_context *pCtx, int nArg, ph7_value **apArg)
|
|||
pArchive = (SyArchive *)ph7_context_alloc_chunk(pCtx, sizeof(SyArchive) + sizeof(zip_raw_data), TRUE, FALSE);
|
||||
if(pArchive == 0) {
|
||||
PH7_VmMemoryError(pCtx->pVm);
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
pRaw = (zip_raw_data *)&pArchive[1];
|
||||
/* Initialize the archive */
|
||||
|
|
1267
engine/vm.c
1267
engine/vm.c
File diff suppressed because it is too large
Load Diff
|
@ -96,7 +96,6 @@ static sxi32 PH7_GenStateCompileArrayEntry(ph7_gen_state *pGen, SyToken *pIn, Sy
|
|||
static sxi32 PH7_GenStateArrayNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pRoot);
|
||||
PH7_PRIVATE sxi32 PH7_CompileArray(ph7_gen_state *pGen, sxi32 iCompileFlag);
|
||||
static sxi32 PH7_GenStateListNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pRoot);
|
||||
PH7_PRIVATE sxi32 PH7_CompileList(ph7_gen_state *pGen, sxi32 iCompileFlag);
|
||||
static sxi32 PH7_GenStateCompileFunc(ph7_gen_state *pGen, SyString *pName, sxi32 iFlags, int bHandleClosure, ph7_vm_func **ppFunc);
|
||||
PH7_PRIVATE sxi32 PH7_CompileLangConstruct(ph7_gen_state *pGen, sxi32 iCompileFlag);
|
||||
PH7_PRIVATE sxi32 PH7_CompileVariable(ph7_gen_state *pGen, sxi32 iCompileFlag);
|
||||
|
@ -129,8 +128,8 @@ static sxi32 PH7_GenStateCompileFunc(ph7_gen_state *pGen, SyString *pName, sxi32
|
|||
static sxi32 PH7_CompileFunction(ph7_gen_state *pGen);
|
||||
static sxi32 PH7_GetProtectionLevel(sxi32 nKeyword);
|
||||
static sxi32 PH7_GenStateCompileClassConstant(ph7_gen_state *pGen, sxi32 iProtection, sxi32 iFlags, ph7_class *pClass);
|
||||
static sxi32 PH7_GenStateCompileClassAttr(ph7_gen_state *pGen, sxi32 iProtection, sxi32 iFlags, ph7_class *pClass);
|
||||
static sxi32 PH7_GenStateCompileClassMethod(ph7_gen_state *pGen, sxi32 iProtection, sxi32 iFlags, int doBody, ph7_class *pClass);
|
||||
static sxi32 PH7_GenStateCompileClassAttr(ph7_gen_state *pGen, sxi32 iProtection, sxi32 iFlags, sxu32 nType, ph7_class *pClass);
|
||||
static sxi32 PH7_GenStateCompileClassMethod(ph7_gen_state *pGen, sxu32 nType, sxi32 iProtection, sxi32 iFlags, int doBody, ph7_class *pClass);
|
||||
static sxi32 PH7_CompileClassInterface(ph7_gen_state *pGen);
|
||||
static sxi32 PH7_GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags);
|
||||
static sxi32 PH7_CompileVirtualClass(ph7_gen_state *pGen);
|
||||
|
|
|
@ -621,7 +621,6 @@ PH7_APIEXPORT void ph7_context_release_value(ph7_context *pCtx, ph7_value *pValu
|
|||
PH7_APIEXPORT int ph7_value_int(ph7_value *pVal, int iValue);
|
||||
PH7_APIEXPORT int ph7_value_int64(ph7_value *pVal, ph7_int64 iValue);
|
||||
PH7_APIEXPORT int ph7_value_bool(ph7_value *pVal, int iBool);
|
||||
PH7_APIEXPORT int ph7_value_null(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_double(ph7_value *pVal, double Value);
|
||||
PH7_APIEXPORT int ph7_value_string(ph7_value *pVal, const char *zString, int nLen);
|
||||
PH7_APIEXPORT int ph7_value_string_format(ph7_value *pVal, const char *zFormat, ...);
|
||||
|
@ -641,14 +640,11 @@ PH7_APIEXPORT int ph7_value_is_int(ph7_value *pVal);
|
|||
PH7_APIEXPORT int ph7_value_is_float(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_is_bool(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_is_string(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_is_null(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_is_numeric(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_is_callback(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_is_callable(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_is_scalar(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_is_array(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_is_object(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_is_resource(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_is_empty(ph7_value *pVal);
|
||||
/* Global Library Management Interfaces */
|
||||
PH7_APIEXPORT int ph7_lib_init(void);
|
||||
PH7_APIEXPORT int ph7_lib_config(int nConfigOp, ...);
|
||||
|
|
|
@ -631,24 +631,26 @@ struct ph7_value {
|
|||
};
|
||||
/* Allowed value types.
|
||||
*/
|
||||
#define MEMOBJ_STRING 0x001 /* Memory value is a UTF-8 string */
|
||||
#define MEMOBJ_INT 0x002 /* Memory value is an integer */
|
||||
#define MEMOBJ_REAL 0x004 /* Memory value is a real number */
|
||||
#define MEMOBJ_BOOL 0x008 /* Memory value is a boolean */
|
||||
#define MEMOBJ_NULL 0x020 /* Memory value is NULL */
|
||||
#define MEMOBJ_HASHMAP 0x040 /* Memory value is a hashmap aka 'array' in the PHP jargon */
|
||||
#define MEMOBJ_OBJ 0x080 /* Memory value is an object [i.e: class instance] */
|
||||
#define MEMOBJ_RES 0x100 /* Memory value is a resource [User private data] */
|
||||
#define MEMOBJ_REFERENCE 0x400 /* Memory value hold a reference (64-bit index) of another ph7_value */
|
||||
#define MEMOBJ_BOOL 0x0001 /* Memory value is a boolean */
|
||||
#define MEMOBJ_CALL 0x0002 /* Memory value is a callback */
|
||||
#define MEMOBJ_CHAR 0x0004 /* Memory value is a char */
|
||||
#define MEMOBJ_INT 0x0008 /* Memory value is an integer */
|
||||
#define MEMOBJ_OBJ 0x0010 /* Memory value is an object [i.e: class instance] */
|
||||
#define MEMOBJ_REAL 0x0020 /* Memory value is a real number */
|
||||
#define MEMOBJ_RES 0x0040 /* Memory value is a resource [User private data] */
|
||||
#define MEMOBJ_STRING 0x0080 /* Memory value is a UTF-8 string */
|
||||
#define MEMOBJ_VOID 0x0100 /* Memory value is a void */
|
||||
#define MEMOBJ_MIXED 0x0200 /* Memory value is mixed */
|
||||
#define MEMOBJ_HASHMAP 0x0800 /* Memory value is a hashmap aka 'array' in the PHP jargon */
|
||||
#define MEMOBJ_NULL 0x1000 /* Memory value is NULL */
|
||||
/* Mask of all known types */
|
||||
#define MEMOBJ_ALL (MEMOBJ_STRING|MEMOBJ_INT|MEMOBJ_REAL|MEMOBJ_BOOL|MEMOBJ_NULL|MEMOBJ_HASHMAP|MEMOBJ_OBJ|MEMOBJ_RES)
|
||||
#define MEMOBJ_ALL (MEMOBJ_STRING|MEMOBJ_INT|MEMOBJ_REAL|MEMOBJ_BOOL|MEMOBJ_NULL|MEMOBJ_HASHMAP|MEMOBJ_OBJ|MEMOBJ_RES|MEMOBJ_CALL|MEMOBJ_CHAR|MEMOBJ_VOID)
|
||||
/* Scalar variables
|
||||
* According to the PHP language reference manual
|
||||
* Scalar variables are those containing an integer, float, string or boolean.
|
||||
* Types array, object and resource are not scalar.
|
||||
*/
|
||||
#define MEMOBJ_SCALAR (MEMOBJ_STRING|MEMOBJ_INT|MEMOBJ_REAL|MEMOBJ_BOOL|MEMOBJ_NULL)
|
||||
#define MEMOBJ_AUX (MEMOBJ_REFERENCE)
|
||||
#define MEMOBJ_SCALAR (MEMOBJ_STRING|MEMOBJ_INT|MEMOBJ_REAL|MEMOBJ_BOOL|MEMOBJ_CHAR|MEMOBJ_VOID|MEMOBJ_NULL)
|
||||
/*
|
||||
* The following macro clear the current ph7_value type and replace
|
||||
* it with the given one.
|
||||
|
@ -955,6 +957,7 @@ struct ph7_vm_func_arg {
|
|||
*/
|
||||
struct ph7_vm_func_static_var {
|
||||
SyString sName; /* Static variable name */
|
||||
sxi32 iFlags; /* Control flags */
|
||||
SySet aByteCode; /* Compiled initialization expression */
|
||||
sxu32 nIdx; /* Object index in the global memory object container */
|
||||
};
|
||||
|
@ -996,6 +999,7 @@ struct ph7_vm_func {
|
|||
SySet aByteCode; /* Compiled function body */
|
||||
SySet aClosureEnv; /* Closure environment (ph7_vm_func_closure_env instace) */
|
||||
sxi32 iFlags; /* VM function configuration */
|
||||
sxu32 nType; /* Return data type expected by this function */
|
||||
SyString sSignature; /* Function signature used to implement function overloading
|
||||
* (Refer to the official documentation for more information
|
||||
* on this powerfull feature)
|
||||
|
@ -1069,6 +1073,7 @@ struct ph7_class_attr {
|
|||
sxi32 iFlags; /* Attribute configuration [i.e: static, variable, constant, etc.] */
|
||||
sxi32 iProtection; /* Protection level [i.e: public, private, protected] */
|
||||
SySet aByteCode; /* Compiled attribute body */
|
||||
sxu32 nType; /* Class attribute data type */
|
||||
sxu32 nIdx; /* Attribute index */
|
||||
sxu32 nLine; /* Line number on which this attribute was defined */
|
||||
};
|
||||
|
@ -1257,9 +1262,11 @@ struct VmFrame {
|
|||
sxi32 iFlags; /* Frame configuration flags (See below) */
|
||||
sxu32 iExceptionJump; /* Exception jump destination */
|
||||
};
|
||||
#define VM_FRAME_EXCEPTION 0x01 /* Special Exception frame */
|
||||
#define VM_FRAME_THROW 0x02 /* An exception was thrown */
|
||||
#define VM_FRAME_CATCH 0x04 /* Catch frame */
|
||||
#define VM_FRAME_ACTIVE 0x01 /* Active call frame */
|
||||
#define VM_FRAME_LOOP 0x02 /* Active loop frame */
|
||||
#define VM_FRAME_EXCEPTION 0x04 /* Special Exception frame */
|
||||
#define VM_FRAME_THROW 0x08 /* An exception was thrown */
|
||||
#define VM_FRAME_CATCH 0x10 /* Catch frame */
|
||||
/*
|
||||
* When a debug stacktrace is extracted from Virtual Machine, all information about
|
||||
* calls (file, line, class, method, arguments) are stored in this structure.
|
||||
|
@ -1382,16 +1389,18 @@ enum iErrCode {
|
|||
enum ph7_vm_op {
|
||||
PH7_OP_DONE = 1, /* Done */
|
||||
PH7_OP_HALT, /* Halt */
|
||||
PH7_OP_DECLARE, /* Declare a variable */
|
||||
PH7_OP_LOAD, /* Load memory object */
|
||||
PH7_OP_LOADC, /* Load constant */
|
||||
PH7_OP_LOAD_IDX, /* Load array entry */
|
||||
PH7_OP_LOAD_MAP, /* Load hashmap('array') */
|
||||
PH7_OP_LOAD_LIST, /* Load list */
|
||||
PH7_OP_LOAD_CLOSURE, /* Load closure */
|
||||
PH7_OP_NOOP, /* NOOP */
|
||||
PH7_OP_JMP, /* Unconditional jump */
|
||||
PH7_OP_JZ, /* Jump on zero (FALSE jump) */
|
||||
PH7_OP_JNZ, /* Jump on non-zero (TRUE jump) */
|
||||
PH7_OP_JMPZ, /* Jump on zero (FALSE jump) */
|
||||
PH7_OP_JMPNZ, /* Jump on non-zero (TRUE jump) */
|
||||
PH7_OP_JMPLFB, /* Jump loop frame begin */
|
||||
PH7_OP_JMPLFE, /* Jump loop frame end */
|
||||
PH7_OP_POP, /* Stack POP */
|
||||
PH7_OP_CVT_INT, /* Integer cast */
|
||||
PH7_OP_CVT_STR, /* String cast */
|
||||
|
@ -1414,8 +1423,6 @@ enum ph7_vm_op {
|
|||
PH7_OP_GE, /* Greater or equal '>=' */
|
||||
PH7_OP_EQ, /* Equal '==' */
|
||||
PH7_OP_NEQ, /* Not equal '!=' */
|
||||
PH7_OP_TEQ, /* Type equal '===' */
|
||||
PH7_OP_TNE, /* Type not equal '!==' */
|
||||
PH7_OP_BAND, /* Bitwise and '&' */
|
||||
PH7_OP_BXOR, /* Bitwise xor '^' */
|
||||
PH7_OP_BOR, /* Bitwise or '|' */
|
||||
|
@ -1429,6 +1436,7 @@ enum ph7_vm_op {
|
|||
PH7_OP_SWAP, /* Stack swap */
|
||||
PH7_OP_YIELD, /* Stack yield */
|
||||
PH7_OP_CVT_BOOL, /* Boolean cast */
|
||||
PH7_OP_CVT_CHAR, /* Char cast */
|
||||
PH7_OP_CVT_NUMC, /* Numeric (integer,real or both) type cast */
|
||||
PH7_OP_INCR, /* Increment ++ */
|
||||
PH7_OP_DECR, /* Decrement -- */
|
||||
|
@ -1445,12 +1453,11 @@ enum ph7_vm_op {
|
|||
PH7_OP_BOR_STORE, /* Bitor and store '|=' */
|
||||
PH7_OP_BXOR_STORE, /* Bitxor and store '^=' */
|
||||
PH7_OP_CONSUME, /* Consume VM output */
|
||||
PH7_OP_LOAD_REF, /* Load reference */
|
||||
PH7_OP_STORE_REF, /* Store a reference to a variable*/
|
||||
PH7_OP_MEMBER, /* Class member run-time access */
|
||||
PH7_OP_CVT_NULL, /* NULL cast */
|
||||
PH7_OP_CVT_ARRAY, /* Array cast */
|
||||
PH7_OP_CVT_OBJ, /* Object cast */
|
||||
PH7_OP_CVT_CALL, /* Callback cast */
|
||||
PH7_OP_CVT_RES, /* Resource cast */
|
||||
PH7_OP_CVT_VOID, /* Void cast */
|
||||
PH7_OP_CLASS_INIT, /* Class init */
|
||||
PH7_OP_INTERFACE_INIT,/* Interface init */
|
||||
PH7_OP_FOREACH_INIT, /* For each init */
|
||||
|
@ -1460,7 +1467,6 @@ enum ph7_vm_op {
|
|||
PH7_OP_POP_EXCEPTION, /* POP an exception */
|
||||
PH7_OP_THROW, /* Throw exception */
|
||||
PH7_OP_SWITCH, /* Switch operation */
|
||||
PH7_OP_ERR_CTRL /* Error control */
|
||||
};
|
||||
/* -- END-OF INSTRUCTIONS -- */
|
||||
/*
|
||||
|
@ -1479,7 +1485,6 @@ enum ph7_expr_id {
|
|||
EXPR_OP_UMINUS, /* Unary minus */
|
||||
EXPR_OP_UPLUS, /* Unary plus */
|
||||
EXPR_OP_TYPECAST, /* Type cast [i.e: (int),(float),(string)...] */
|
||||
EXPR_OP_ALT, /* @ */
|
||||
EXPR_OP_INSTOF, /* instanceof */
|
||||
EXPR_OP_LOGNOT, /* logical not ! */
|
||||
EXPR_OP_MUL, /* Multiplication */
|
||||
|
@ -1495,8 +1500,6 @@ enum ph7_expr_id {
|
|||
EXPR_OP_GE, /* Greater equal */
|
||||
EXPR_OP_EQ, /* Equal == */
|
||||
EXPR_OP_NE, /* Not equal != <> */
|
||||
EXPR_OP_TEQ, /* Type equal === */
|
||||
EXPR_OP_TNE, /* Type not equal !== */
|
||||
EXPR_OP_BAND, /* Bitwise and '&' */
|
||||
EXPR_OP_REF, /* Reference operator '&' */
|
||||
EXPR_OP_XOR, /* bitwise xor '^' */
|
||||
|
@ -1561,15 +1564,12 @@ enum ph7_expr_id {
|
|||
/* The number '8' is reserved for PH7_TK_ID */
|
||||
#define PH7_KEYWORD_IMPORT 9 /* import */
|
||||
#define PH7_KEYWORD_REQUIRE 10 /* require */
|
||||
#define PH7_KEYWORD_ELIF 0x4000000 /* elseif: MUST BE A POWER OF TWO */
|
||||
#define PH7_KEYWORD_ELSE 0x8000000 /* else: MUST BE A POWER OF TWO */
|
||||
#define PH7_KEYWORD_ELSE 12 /* else */
|
||||
#define PH7_KEYWORD_IF 13 /* if */
|
||||
#define PH7_KEYWORD_FINAL 14 /* final */
|
||||
#define PH7_KEYWORD_LIST 15 /* list */
|
||||
#define PH7_KEYWORD_STATIC 16 /* static */
|
||||
#define PH7_KEYWORD_CASE 17 /* case */
|
||||
#define PH7_KEYWORD_SELF 18 /* self */
|
||||
#define PH7_KEYWORD_FUNCTION 19 /* function */
|
||||
#define PH7_KEYWORD_NAMESPACE 20 /* namespace */
|
||||
#define PH7_KEYWORD_CLONE 0x80 /* clone: MUST BE A POWER OF TWO */
|
||||
#define PH7_KEYWORD_NEW 0x100 /* new: MUST BE A POWER OF TWO */
|
||||
|
@ -1578,8 +1578,6 @@ enum ph7_expr_id {
|
|||
#define PH7_KEYWORD_USING 24 /* using */
|
||||
#define PH7_KEYWORD_WHILE 26 /* while */
|
||||
#define PH7_KEYWORD_EVAL 27 /* eval */
|
||||
#define PH7_KEYWORD_VAR 28 /* var */
|
||||
#define PH7_KEYWORD_ARRAY 0x200 /* array: MUST BE A POWER OF TWO */
|
||||
#define PH7_KEYWORD_VIRTUAL 29 /* virtual */
|
||||
#define PH7_KEYWORD_TRY 30 /* try */
|
||||
#define PH7_KEYWORD_DEFAULT 31 /* default */
|
||||
|
@ -1590,9 +1588,7 @@ enum ph7_expr_id {
|
|||
#define PH7_KEYWORD_FINALLY 36 /* finally */
|
||||
#define PH7_KEYWORD_IMPLEMENTS 39 /* implements */
|
||||
#define PH7_KEYWORD_INCLUDE 41 /* include */
|
||||
#define PH7_KEYWORD_EMPTY 42 /* empty */
|
||||
#define PH7_KEYWORD_INSTANCEOF 0x400 /* instanceof: MUST BE A POWER OF TWO */
|
||||
#define PH7_KEYWORD_ISSET 43 /* isset */
|
||||
#define PH7_KEYWORD_PARENT 44 /* parent */
|
||||
#define PH7_KEYWORD_PRIVATE 45 /* private */
|
||||
#define PH7_KEYWORD_FOR 48 /* for */
|
||||
|
@ -1603,7 +1599,6 @@ enum ph7_expr_id {
|
|||
#define PH7_KEYWORD_CATCH 53 /* catch */
|
||||
#define PH7_KEYWORD_RETURN 54 /* return */
|
||||
#define PH7_KEYWORD_BREAK 55 /* break */
|
||||
#define PH7_KEYWORD_UNSET 0x800 /* unset: MUST BE A POWER OF TWO */
|
||||
#define PH7_KEYWORD_VOID 0x1000 /* void: MUST BE A POWER OF TWO */
|
||||
#define PH7_KEYWORD_CHAR 0x2000 /* char: MUST BE A POWER OF TWO */
|
||||
#define PH7_KEYWORD_BOOL 0x4000 /* bool: MUST BE A POWER OF TWO */
|
||||
|
@ -1614,6 +1609,8 @@ enum ph7_expr_id {
|
|||
#define PH7_KEYWORD_CALLBACK 0x80000 /* callback: MUST BE A POWER OF TWO */
|
||||
#define PH7_KEYWORD_RESOURCE 0x100000 /* resource: MUST BE A POWER OF TWO */
|
||||
#define PH7_KEYWORD_MIXED 0x200000 /* mixed: MUST BE A POWER OF TWO */
|
||||
|
||||
#define PH7_KEYWORD_TYPEDEF (PH7_KEYWORD_VOID|PH7_KEYWORD_CHAR|PH7_KEYWORD_BOOL|PH7_KEYWORD_INT|PH7_KEYWORD_FLOAT|PH7_KEYWORD_STRING|PH7_KEYWORD_OBJECT|PH7_KEYWORD_CALLBACK|PH7_KEYWORD_RESOURCE|PH7_KEYWORD_MIXED)
|
||||
/* JSON encoding/decoding related definition */
|
||||
enum json_err_code {
|
||||
JSON_ERROR_NONE = 0, /* No error has occurred. */
|
||||
|
@ -1624,7 +1621,7 @@ enum json_err_code {
|
|||
JSON_ERROR_UTF8 /* Malformed UTF-8 characters */
|
||||
};
|
||||
/* memobj.c function prototypes */
|
||||
PH7_PRIVATE sxi32 PH7_MemObjDump(SyBlob *pOut, ph7_value *pObj, int ShowType, int nTab, int nDepth, int isRef);
|
||||
PH7_PRIVATE sxi32 PH7_MemObjDump(SyBlob *pOut, ph7_value *pObj, int ShowType, int nTab, int nDepth);
|
||||
PH7_PRIVATE const char *PH7_MemObjTypeDump(ph7_value *pVal);
|
||||
PH7_PRIVATE sxi32 PH7_MemObjAdd(ph7_value *pObj1, ph7_value *pObj2, int bAddStore);
|
||||
PH7_PRIVATE sxi32 PH7_MemObjCmp(ph7_value *pObj1, ph7_value *pObj2, int bStrict, int iNest);
|
||||
|
@ -1646,10 +1643,13 @@ PH7_PRIVATE sxi32 PH7_MemObjIsEmpty(ph7_value *pObj);
|
|||
PH7_PRIVATE sxi32 PH7_MemObjToHashmap(ph7_value *pObj);
|
||||
PH7_PRIVATE sxi32 PH7_MemObjToObject(ph7_value *pObj);
|
||||
PH7_PRIVATE sxi32 PH7_MemObjToString(ph7_value *pObj);
|
||||
PH7_PRIVATE sxi32 PH7_MemObjToNull(ph7_value *pObj);
|
||||
PH7_PRIVATE sxi32 PH7_MemObjToReal(ph7_value *pObj);
|
||||
PH7_PRIVATE sxi32 PH7_MemObjToInteger(ph7_value *pObj);
|
||||
PH7_PRIVATE sxi32 PH7_MemObjToBool(ph7_value *pObj);
|
||||
PH7_PRIVATE sxi32 PH7_MemObjToCallback(ph7_value *pObj);
|
||||
PH7_PRIVATE sxi32 PH7_MemObjToResource(ph7_value *pObj);
|
||||
PH7_PRIVATE sxi32 PH7_CheckVarCompat(ph7_value *pObj, int nType);
|
||||
PH7_PRIVATE sxi32 PH7_MemObjSafeStore(ph7_value *pSrc, ph7_value *pDest);
|
||||
PH7_PRIVATE sxi64 PH7_TokenValueToInt64(SyString *pData);
|
||||
/* lex.c function prototypes */
|
||||
PH7_PRIVATE sxi32 PH7_TokenizeRawText(const char *zInput, sxu32 nLen, SySet *pOut);
|
||||
|
@ -1719,7 +1719,6 @@ PH7_PRIVATE sxi32 PH7_CompileLiteral(ph7_gen_state *pGen, sxi32 iCompileFlag);
|
|||
PH7_PRIVATE sxi32 PH7_CompileSimpleString(ph7_gen_state *pGen, sxi32 iCompileFlag);
|
||||
PH7_PRIVATE sxi32 PH7_CompileString(ph7_gen_state *pGen, sxi32 iCompileFlag);
|
||||
PH7_PRIVATE sxi32 PH7_CompileArray(ph7_gen_state *pGen, sxi32 iCompileFlag);
|
||||
PH7_PRIVATE sxi32 PH7_CompileList(ph7_gen_state *pGen, sxi32 iCompileFlag);
|
||||
PH7_PRIVATE sxi32 PH7_CompileClosure(ph7_gen_state *pGen, sxi32 iCompileFlag);
|
||||
PH7_PRIVATE sxi32 PH7_InitCodeGenerator(ph7_vm *pVm, ProcConsumer xErr, void *pErrData);
|
||||
PH7_PRIVATE sxi32 PH7_ResetCodeGenerator(ph7_vm *pVm, ProcConsumer xErr, void *pErrData);
|
||||
|
@ -1736,7 +1735,6 @@ PH7_PRIVATE sxi32 PH7_HashmapRelease(ph7_hashmap *pMap, int FreeDS);
|
|||
PH7_PRIVATE void PH7_HashmapUnref(ph7_hashmap *pMap);
|
||||
PH7_PRIVATE sxi32 PH7_HashmapLookup(ph7_hashmap *pMap, ph7_value *pKey, ph7_hashmap_node **ppNode);
|
||||
PH7_PRIVATE sxi32 PH7_HashmapInsert(ph7_hashmap *pMap, ph7_value *pKey, ph7_value *pVal);
|
||||
PH7_PRIVATE sxi32 PH7_HashmapInsertByRef(ph7_hashmap *pMap, ph7_value *pKey, sxu32 nRefIdx);
|
||||
PH7_PRIVATE sxi32 PH7_HashmapUnion(ph7_hashmap *pLeft, ph7_hashmap *pRight);
|
||||
PH7_PRIVATE void PH7_HashmapUnlinkNode(ph7_hashmap_node *pNode, int bRestore);
|
||||
PH7_PRIVATE sxi32 PH7_HashmapDup(ph7_hashmap *pSrc, ph7_hashmap *pDest);
|
||||
|
@ -1748,6 +1746,7 @@ PH7_PRIVATE void PH7_HashmapExtractNodeKey(ph7_hashmap_node *pNode, ph7_value *p
|
|||
PH7_PRIVATE void PH7_RegisterHashmapFunctions(ph7_vm *pVm);
|
||||
PH7_PRIVATE sxi32 PH7_HashmapDump(SyBlob *pOut, ph7_hashmap *pMap, int ShowType, int nTab, int nDepth);
|
||||
PH7_PRIVATE sxi32 PH7_HashmapWalk(ph7_hashmap *pMap, int (*xWalk)(ph7_value *, ph7_value *, void *), void *pUserData);
|
||||
PH7_PRIVATE sxi32 PH7_HashmapCast(ph7_value *pObj, sxi32 nType);
|
||||
PH7_PRIVATE int PH7_HashmapValuesToSet(ph7_hashmap *pMap, SySet *pOut);
|
||||
/* builtin.c function prototypes */
|
||||
PH7_PRIVATE sxi32 PH7_InputFormat(int (*xConsumer)(ph7_context *, const char *, int, void *),
|
||||
|
@ -1760,7 +1759,7 @@ PH7_PRIVATE sxi32 PH7_ParseIniString(ph7_context *pCtx, const char *zIn, sxu32 n
|
|||
/* oo.c function prototypes */
|
||||
PH7_PRIVATE ph7_class_info *PH7_NewClassInfo(ph7_vm *pVm, const SyString *pName);
|
||||
PH7_PRIVATE ph7_class *PH7_NewRawClass(ph7_vm *pVm, const SyString *pName);
|
||||
PH7_PRIVATE ph7_class_attr *PH7_NewClassAttr(ph7_vm *pVm, const SyString *pName, sxu32 nLine, sxi32 iProtection, sxi32 iFlags);
|
||||
PH7_PRIVATE ph7_class_attr *PH7_NewClassAttr(ph7_vm *pVm, const SyString *pName, sxu32 nLine, sxi32 iProtection, sxi32 iFlags, sxu32 nType);
|
||||
PH7_PRIVATE ph7_class_method *PH7_NewClassMethod(ph7_vm *pVm, ph7_class *pClass, const SyString *pName, sxu32 nLine,
|
||||
sxi32 iProtection, sxi32 iFlags, sxi32 iFuncFlags);
|
||||
PH7_PRIVATE ph7_class_method *PH7_ClassExtractMethod(ph7_class *pClass, const char *zName, sxu32 nByte);
|
||||
|
@ -1769,7 +1768,7 @@ PH7_PRIVATE sxi32 PH7_ClassInstallAttr(ph7_class *pClass, ph7_class_attr *pAttr)
|
|||
PH7_PRIVATE sxi32 PH7_ClassInstallMethod(ph7_class *pClass, ph7_class_method *pMeth);
|
||||
PH7_PRIVATE sxi32 PH7_ClassInherit(ph7_vm *pVm, ph7_class *pSub, ph7_class *pBase);
|
||||
PH7_PRIVATE sxi32 PH7_ClassInterfaceInherit(ph7_class *pSub, ph7_class *pBase);
|
||||
PH7_PRIVATE sxi32 PH7_ClassImplement(ph7_class *pMain, ph7_class *pInterface);
|
||||
PH7_PRIVATE sxi32 PH7_ClassImplement(ph7_vm *pVm, ph7_class *pMain, ph7_class *pInterface);
|
||||
PH7_PRIVATE ph7_class_instance *PH7_NewClassInstance(ph7_vm *pVm, ph7_class *pClass);
|
||||
PH7_PRIVATE ph7_class_instance *PH7_CloneClassInstance(ph7_class_instance *pSrc);
|
||||
PH7_PRIVATE sxi32 PH7_ClassInstanceCmp(ph7_class_instance *pLeft, ph7_class_instance *pRight, int bStrict, int iNest);
|
||||
|
|
|
@ -151,7 +151,7 @@ static sxi32 VmJsonEncode(
|
|||
ph7_context *pCtx = pData->pCtx;
|
||||
int iFlags = pData->iFlags;
|
||||
int nByte;
|
||||
if(ph7_value_is_null(pIn) || ph7_value_is_resource(pIn)) {
|
||||
if(ph7_value_is_void(pIn) || ph7_value_is_resource(pIn)) {
|
||||
/* null */
|
||||
ph7_result_string(pCtx, "null", (int)sizeof("null") - 1);
|
||||
} else if(ph7_value_is_bool(pIn)) {
|
||||
|
@ -620,7 +620,7 @@ static sxi32 VmJsonDecode(
|
|||
/* Reflect the JSON image */
|
||||
if(pDecoder->pIn->nType & JSON_TK_NULL) {
|
||||
/* Nullify the value.*/
|
||||
ph7_value_null(pWorker);
|
||||
ph7_value_void(pWorker);
|
||||
} else if(pDecoder->pIn->nType & (JSON_TK_TRUE | JSON_TK_FALSE)) {
|
||||
/* Boolean value */
|
||||
ph7_value_bool(pWorker, (pDecoder->pIn->nType & JSON_TK_TRUE) ? 1 : 0);
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
class Program {
|
||||
private callback $condition = bool(int $x) { return ($x > 100); };
|
||||
private int[] $numbers = {34, 56, 22, 1, 5, 67, 897, 123, 55, 101};
|
||||
|
||||
int[] filter(callback $condition, int[] $numbers) {
|
||||
int $len = sizeof($numbers);
|
||||
int[] $filtered;
|
||||
for(int $i = 0; $i < $len; $i++) {
|
||||
if($condition($numbers[$i])) {
|
||||
$filtered[] = $numbers[$i];
|
||||
}
|
||||
}
|
||||
return $filtered;
|
||||
}
|
||||
|
||||
void main() {
|
||||
int[] $filtered = $this->filter($this->condition, $this->numbers);
|
||||
var_dump($filtered);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Should output
|
||||
|
||||
Array ( [0] => 897 [1] => 123 )
|
||||
*/
|
|
@ -0,0 +1,8 @@
|
|||
array(int, 3) {
|
||||
[0] =>
|
||||
int(897)
|
||||
[1] =>
|
||||
int(123)
|
||||
[2] =>
|
||||
int(101)
|
||||
}
|
|
@ -1,21 +1,22 @@
|
|||
class Program {
|
||||
|
||||
private function num2Roman($num) {
|
||||
$n = intval($num);
|
||||
$result = '';
|
||||
$lookup = array('M' => 1000, 'CM' => 900, 'D' => 500, 'CD' => 400,
|
||||
private string num2Roman(int $num) {
|
||||
int $n = $num;
|
||||
string $result = '';
|
||||
int[] $lookup = {'M' => 1000, 'CM' => 900, 'D' => 500, 'CD' => 400,
|
||||
'C' => 100, 'XC' => 90, 'L' => 50, 'XL' => 40,
|
||||
'X' => 10, 'IX' => 9, 'V' => 5, 'IV' => 4, 'I' => 1);
|
||||
'X' => 10, 'IX' => 9, 'V' => 5, 'IV' => 4, 'I' => 1};
|
||||
|
||||
int $matches;
|
||||
foreach($lookup as $roman => $value) {
|
||||
$matches = intval($n / $value);
|
||||
$matches = (int) ($n / $value);
|
||||
$result += str_repeat($roman, $matches);
|
||||
$n = $n % $value;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function main() {
|
||||
public void main() {
|
||||
print(' 7 => ' + $this->num2Roman(7) + "\n");
|
||||
print(' 9 => ' + $this->num2Roman(9) + "\n");
|
||||
print(' 11 => ' + $this->num2Roman(11) + "\n");
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
class Program {
|
||||
|
||||
void test_assert(mixed $param) {
|
||||
assert("is_bool($param);");
|
||||
}
|
||||
|
||||
void main() {
|
||||
callback $assert_fail = void(string $file, int $line, string $code) {
|
||||
print("Assertion failed ...\n");
|
||||
};
|
||||
assert_options(ASSERT_ACTIVE, true);
|
||||
assert_options(ASSERT_BAIL, false);
|
||||
assert_options(ASSERT_WARNING, false);
|
||||
assert_options(ASSERT_CALLBACK, $assert_fail);
|
||||
$this->test_assert(true);
|
||||
$this->test_assert(1);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
Assertion failed ...
|
|
@ -0,0 +1,17 @@
|
|||
class Program {
|
||||
|
||||
string fmt_binary(int $x, int $numbits = 8) {
|
||||
string $bin;
|
||||
string $rtnval = '';
|
||||
$bin = decbin($x);
|
||||
$bin = substr(str_repeat(0, $numbits), 0, $numbits - strlen($bin)) + $bin;
|
||||
for($x = 0; $x < $numbits / 4; $x++) {
|
||||
$rtnval += ' ' + substr($bin, $x * 4, 4);
|
||||
}
|
||||
return ltrim($rtnval);
|
||||
}
|
||||
|
||||
void main() {
|
||||
var_dump($this->fmt_binary(2541));
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
string(9 '0000 1001')
|
|
@ -0,0 +1,107 @@
|
|||
class Brainfuck {
|
||||
private string $code;
|
||||
private int $code_pointer;
|
||||
private int[] $cells;
|
||||
private int $pointer;
|
||||
private string $input;
|
||||
private int $input_pointer;
|
||||
private int[] $buffer;
|
||||
private string $output;
|
||||
|
||||
public void __construct(string $code, string $input = NULL) {
|
||||
$this->code = $code;
|
||||
$this->input = $input;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while ($this->code_pointer < strlen($this->code)) {
|
||||
$this->interpret($this->code[$this->code_pointer]);
|
||||
$this->code_pointer++;
|
||||
}
|
||||
print($this->output);
|
||||
}
|
||||
|
||||
private void interpret(string $command) {
|
||||
if(!$this->cells[$this->pointer]) {
|
||||
$this->cells[$this->pointer] = 0;
|
||||
}
|
||||
switch ($command) {
|
||||
case '>' :
|
||||
$this->pointer++;
|
||||
break;
|
||||
case '<' :
|
||||
$this->pointer--;
|
||||
break;
|
||||
case '+' :
|
||||
$this->cells[$this->pointer]++;
|
||||
if($this->cells[$this->pointer] > 255) {
|
||||
$this->cells[$this->pointer] = 0;
|
||||
}
|
||||
break;
|
||||
case '-' :
|
||||
$this->cells[$this->pointer]--;
|
||||
if($this->cells[$this->pointer] < 0) {
|
||||
$this->cells[$this->pointer] = 255;
|
||||
}
|
||||
break;
|
||||
case '.' :
|
||||
$this->output += chr($this->cells[$this->pointer]);
|
||||
break;
|
||||
case ',' :
|
||||
$this->cells[$this->pointer] = $this->input[$this->input_pointer] ? ord($this->input[$this->input_pointer]) : 0;
|
||||
$this->input_pointer++;
|
||||
break;
|
||||
case '[' :
|
||||
if($this->cells[$this->pointer] == 0) {
|
||||
int $delta = 1;
|
||||
while($delta && $this->code_pointer++ < strlen($this->code)) {
|
||||
switch ($this->code[$this->code_pointer]) {
|
||||
case '[' :
|
||||
$delta++;
|
||||
break;
|
||||
case ']' :
|
||||
$delta--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->buffer[] = $this->code_pointer;
|
||||
}
|
||||
break;
|
||||
case ']' :
|
||||
$this->code_pointer = array_pop($this->buffer) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class Program {
|
||||
|
||||
void main() {
|
||||
object $bf;
|
||||
string $code;
|
||||
resource $dir;
|
||||
string $file;
|
||||
string[] $files;
|
||||
string $input;
|
||||
$dir = opendir('tests/data/brainfuck');
|
||||
while($file = readdir($dir)) {
|
||||
if($file == '.' || $file == '..') {
|
||||
continue;
|
||||
}
|
||||
$files[] = $file;
|
||||
}
|
||||
sort($files);
|
||||
unset($file);
|
||||
foreach($files as $file) {
|
||||
print('Executing "' + $file + '"' + "\n");
|
||||
$code = file_get_contents('tests/data/brainfuck/' + $file);
|
||||
$bf = new Brainfuck($code, $input);
|
||||
$bf->run();
|
||||
print("\n");
|
||||
}
|
||||
closedir($dir);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
Executing "array.bf"
|
||||
EC
|
||||
Executing "hello_world.bf"
|
||||
Hello World!
|
||||
|
||||
Executing "sierpinski.bf"
|
||||
*
|
||||
* *
|
||||
* *
|
||||
* * * *
|
||||
* *
|
||||
* * * *
|
||||
* * * *
|
||||
* * * * * * * *
|
||||
* *
|
||||
* * * *
|
||||
* * * *
|
||||
* * * * * * * *
|
||||
* * * *
|
||||
* * * * * * * *
|
||||
* * * * * * * *
|
||||
* * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* * * *
|
||||
* * * *
|
||||
* * * * * * * *
|
||||
* * * *
|
||||
* * * * * * * *
|
||||
* * * * * * * *
|
||||
* * * * * * * * * * * * * * * *
|
||||
* * * *
|
||||
* * * * * * * *
|
||||
* * * * * * * *
|
||||
* * * * * * * * * * * * * * * *
|
||||
* * * * * * * *
|
||||
* * * * * * * * * * * * * * * *
|
||||
* * * * * * * * * * * * * * * *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
class Program {
|
||||
|
||||
void main(string[] $args) {
|
||||
callback $y = void() {
|
||||
callback $a = 'printf';
|
||||
$a("I'm alive\n");
|
||||
var_dump($a);
|
||||
};
|
||||
$y();
|
||||
var_dump($y);
|
||||
string $a = 'printf';
|
||||
var_dump($a);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
I'm alive
|
||||
callback(6 'printf')
|
||||
callback(11 '{closure_1}')
|
||||
string(6 'printf')
|
|
@ -0,0 +1,28 @@
|
|||
class Program {
|
||||
|
||||
private string center_text(string $word){
|
||||
int $tot_width = 30;
|
||||
char $symbol = '-';
|
||||
int $middle = (int) round($tot_width/2);
|
||||
int $length_word = strlen($word);
|
||||
int $middle_word = (int) round($length_word / 2);
|
||||
int $last_position = $middle + $middle_word;
|
||||
int $number_of_spaces = $middle - $middle_word;
|
||||
string $result = sprintf("%'{$symbol}{$last_position}s", $word);
|
||||
for(int $i = 0; $i < $number_of_spaces; $i++) {
|
||||
$result += "$symbol";
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
void main() {
|
||||
string $str = 'Example text';
|
||||
print($this->center_text($str));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Should output
|
||||
---------------This is some text------------
|
||||
*/
|
|
@ -0,0 +1 @@
|
|||
---------Example text---------
|
|
@ -0,0 +1,19 @@
|
|||
class Test1 {
|
||||
}
|
||||
|
||||
class Test2 extends Test1 {
|
||||
}
|
||||
|
||||
class Program {
|
||||
object $t;
|
||||
|
||||
void test(Test1 $t = new Test2) {
|
||||
$this->t = $t;
|
||||
var_dump($this->t);
|
||||
}
|
||||
|
||||
void main() {
|
||||
$this->test();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
object(Test2) {
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
class Button {
|
||||
public callback $OnBeforeClick;
|
||||
public callback $OnAfterClick;
|
||||
public string $Name;
|
||||
|
||||
public void __construct() {
|
||||
$this->Name = 'MyButton';
|
||||
}
|
||||
|
||||
public void Click() {
|
||||
$this->DoBeforeClick();
|
||||
print('Click!');
|
||||
$this->DoAfterClick();
|
||||
}
|
||||
|
||||
private void DoBeforeClick() {
|
||||
if($this->OnBeforeClick) {
|
||||
callback $event = $this->OnBeforeClick;
|
||||
$event($this);
|
||||
}
|
||||
}
|
||||
|
||||
private void DoAfterClick() {
|
||||
if($this->OnAfterClick) {
|
||||
callback $event = $this->OnAfterClick;
|
||||
$event($this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Program {
|
||||
|
||||
void main() {
|
||||
object $MyWidget = new Button();
|
||||
$MyWidget->OnBeforeClick = void(object $Sender) { print($Sender->Name + ' (Before Click)'); };
|
||||
$MyWidget->OnAfterClick = void(object $Sender) { print($Sender->Name + ' (After Click)'); };
|
||||
$MyWidget->Click();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
MyButton (Before Click)Click!MyButton (After Click)
|
|
@ -0,0 +1,36 @@
|
|||
class Operations {
|
||||
|
||||
public callback ops(int $x, int $y, string $op){
|
||||
switch($op) {
|
||||
case 'ADD':
|
||||
return int() using ($x, $y) {
|
||||
return $x + $y;
|
||||
};
|
||||
break;
|
||||
case 'SUB':
|
||||
return int() using ($x, $y) {
|
||||
return $x - $y;
|
||||
};
|
||||
break;
|
||||
default:
|
||||
return string() {
|
||||
return 'Operation is not supported by class.';
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Program {
|
||||
|
||||
void main() {
|
||||
callback $fn;
|
||||
object $op = new Operations();
|
||||
$fn = $op->ops(6, 7, 'ADD');
|
||||
print($fn() + "\n");
|
||||
$fn = $op->ops(6, 2, 'SUB');
|
||||
print($fn() + "\n");
|
||||
$fn = $op->ops(6, 7, 'MUL');
|
||||
print($fn() + "\n");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
13
|
||||
4
|
||||
Operation is not supported by class.
|
|
@ -0,0 +1,43 @@
|
|||
class Program {
|
||||
private const MY_CONST = 12 ^ 0x3FD;
|
||||
private callback $callback_test = void(){ print("Welcome everyone!\n");};
|
||||
private static int $value = 4 + 4 * 4;
|
||||
|
||||
void callable(callback $callback = void(){ print("Hello world!\n");}) {
|
||||
$callback();
|
||||
}
|
||||
|
||||
void complexArgs(string $name = 'AerScript' + $this->someStr(), int $age = 10*2+5) {
|
||||
print("Name = $name\n");
|
||||
print("Age = $age\n");
|
||||
}
|
||||
|
||||
string someStr() {
|
||||
return 'ABC';
|
||||
}
|
||||
|
||||
bool someTrue() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool someFalse() {
|
||||
return false;
|
||||
}
|
||||
|
||||
int main() {
|
||||
static float $f = 4 + 2.4 * 9.1;
|
||||
var_dump($this->MY_CONST);
|
||||
var_dump($this->callback_test);
|
||||
var_dump($this->value);
|
||||
var_dump($f);
|
||||
$this->complexArgs();
|
||||
$this->complexArgs('Me');
|
||||
$this->callable();
|
||||
$this->callable(void(){ print("Welcome guest!\n");});
|
||||
$this->callable($this->callback_test);
|
||||
$this->someTrue() || print("someTrue() failed\n");
|
||||
$this->someFalse() || print("someFalse() failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
int(1009)
|
||||
callback(11 '{closure_1}')
|
||||
int(20)
|
||||
float(25.84)
|
||||
Name = AerScriptABC
|
||||
Age = 25
|
||||
Name = Me
|
||||
Age = 25
|
||||
Hello world!
|
||||
Welcome guest!
|
||||
Welcome everyone!
|
||||
someFalse() failed
|
|
@ -0,0 +1,16 @@
|
|||
class Program {
|
||||
|
||||
void test(int $a = (int(int $a, int $b, int $c){return $a+$b+$c;})(14, 10+2, 15), int $b = 0, int $c = 98) {
|
||||
print($a + PHP_EOL);
|
||||
print($b + PHP_EOL);
|
||||
print($c + PHP_EOL);
|
||||
}
|
||||
|
||||
void main() {
|
||||
$this->test();
|
||||
$this->test(512);
|
||||
$this->test(1024, 32);
|
||||
$this->test(1000, 2000, 4000);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
41
|
||||
0
|
||||
98
|
||||
512
|
||||
0
|
||||
98
|
||||
1024
|
||||
32
|
||||
98
|
||||
1000
|
||||
2000
|
||||
4000
|
|
@ -0,0 +1,22 @@
|
|||
>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>
|
||||
>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>
|
||||
>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>
|
||||
>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>
|
||||
>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>
|
||||
<<<<<<<<<<
|
||||
first put the desired index in front of the array
|
||||
++++
|
||||
we are done if there is a zero in the current tag cell
|
||||
[
|
||||
decrement the current tag cell
|
||||
-
|
||||
move the value in the current tag cell to the next if it is not zero
|
||||
[>>+<<-]
|
||||
move to next tag cell
|
||||
>>
|
||||
we found it: print the desired element
|
||||
]>.
|
||||
now print another
|
||||
<<<<<<<<<
|
||||
++
|
||||
[-[>>+<<-]>>]>.
|
|
@ -0,0 +1 @@
|
|||
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.
|
|
@ -0,0 +1,5 @@
|
|||
++++++++[>+>++++<<-]>++>>+<[-[>>+<<-]+>>]>+[
|
||||
-<<<[
|
||||
->[+[-]+>++>>>-<<]<[<]>>++++++[<<+++++>>-]+<<++.[-]<<
|
||||
]>.>+[>>]>+
|
||||
]
|
|
@ -1,12 +1,12 @@
|
|||
class Program {
|
||||
|
||||
function main() {
|
||||
void main() {
|
||||
$this->b($this->a('First A'), $this->a('Second A'), $this->a('Third A'));
|
||||
}
|
||||
|
||||
function a($p) {
|
||||
$backtrace = debug_backtrace();
|
||||
if(isset($backtrace[0]['args'])) {
|
||||
string a(string $p) {
|
||||
mixed[] $backtrace = debug_backtrace();
|
||||
if(array_key_exists('args', $backtrace[0])) {
|
||||
var_export($backtrace[0]['args']);
|
||||
} else {
|
||||
print("Cannot aquire arguments\n");
|
||||
|
@ -14,7 +14,7 @@ class Program {
|
|||
return $p;
|
||||
}
|
||||
|
||||
function b($p1, $p2, $p3) {
|
||||
void b(string $p1, string $p2, string $p3) {
|
||||
print("$p1, $p2, $p3");
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
class ExceptionHandler {
|
||||
|
||||
public static void printException(Exception $e) {
|
||||
print('Uncaught ' + get_class($e) + ', code: ' + $e->getCode() + "\nMessage: " + htmlentities($e->getMessage()) + "\n");
|
||||
}
|
||||
|
||||
public static void handleException(Exception $e) {
|
||||
self::printException($e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class NewException extends Exception {
|
||||
}
|
||||
|
||||
class Program {
|
||||
|
||||
void main() {
|
||||
callback $handler = void(Exception $e) {
|
||||
ExceptionHandler::handleException($e);
|
||||
};
|
||||
set_exception_handler($handler);
|
||||
try {
|
||||
throw new NewException("Catch me once", 1);
|
||||
} catch(Exception $e) {
|
||||
ExceptionHandler::handleException($e);
|
||||
}
|
||||
throw new Exception("Catch me twice", 2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
Uncaught NewException, code: 1
|
||||
Message: Catch me once
|
||||
Uncaught Exception, code: 2
|
||||
Message: Catch me twice
|
|
@ -0,0 +1,24 @@
|
|||
class Dog {
|
||||
public string $name;
|
||||
public string $color;
|
||||
|
||||
public void __construct(string $name, string $color) {
|
||||
$this->name = $name;
|
||||
$this->color = $color;
|
||||
}
|
||||
|
||||
public callback greet(string $greeting) {
|
||||
return void() using ($greeting) {
|
||||
print("$greeting, I am a {$this->color} dog named {$this->name}\n");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class Program {
|
||||
|
||||
void main() {
|
||||
object $dog = new Dog('Alex', 'red');
|
||||
callback $c = $dog->greet('Hello');
|
||||
$c();
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
Hello, I am a red dog named Alex
|
|
@ -0,0 +1,15 @@
|
|||
class Program {
|
||||
|
||||
int factorial(int $num) {
|
||||
if($num == 0 || $num == 1)
|
||||
return 1;
|
||||
else
|
||||
return $num * $this->factorial($num - 1);
|
||||
}
|
||||
|
||||
void main() {
|
||||
int $num = 7;
|
||||
print('Factorial of ', $num, ' is ', $this->factorial($num), '.');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
Factorial of 7 is 5040.
|
|
@ -0,0 +1,29 @@
|
|||
class Circle {
|
||||
void draw() {
|
||||
print("Circle\n");
|
||||
}
|
||||
}
|
||||
|
||||
class Square {
|
||||
void draw() {
|
||||
print("Square\n");
|
||||
}
|
||||
}
|
||||
|
||||
class Program {
|
||||
|
||||
object ShapeFactoryMethod(string $shape) {
|
||||
switch ($shape) {
|
||||
case "Circle":
|
||||
return new Circle();
|
||||
case "Square":
|
||||
return new Square();
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
$this->ShapeFactoryMethod("Circle")->draw();
|
||||
$this->ShapeFactoryMethod("Square")->draw();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
Circle
|
||||
Square
|
|
@ -1,7 +1,12 @@
|
|||
#!/usr/local/bin/aer
|
||||
class Program {
|
||||
|
||||
public function main() {
|
||||
print('Hello world!');
|
||||
/*
|
||||
* Program entry point.
|
||||
* It does not take any arguments.
|
||||
*/
|
||||
public void main() {
|
||||
print('Hello world!'); // single line comment
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
class Program {
|
||||
|
||||
string num2alpha(int $n) {
|
||||
string $r = '';
|
||||
for(int $i = 1; $n >= 0 && $i < 10; $i++) {
|
||||
$r = chr(0x41 + ($n % pow(26, $i) / pow(26, $i - 1))) + $r;
|
||||
$n -= pow(26, $i);
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
int alpha2num(string $a) {
|
||||
int $r = 0;
|
||||
int $l = strlen($a);
|
||||
for(int $i = 0; $i < $l; $i++) {
|
||||
$r += pow(26, $i) * (ord($a[$l - $i - 1]) - 0x40);
|
||||
}
|
||||
return (int) $r - 1;
|
||||
}
|
||||
|
||||
void main() {
|
||||
import('math');
|
||||
var_dump($this->alpha2num("Salut"), $this->num2alpha(1723), $this->num2alpha(9854), $this->alpha2num("Base64"));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
int(9293725)
|
||||
string(3 'BNH')
|
||||
string(3 'NOA')
|
||||
int(39764075)
|
|
@ -0,0 +1,42 @@
|
|||
interface iVehicle {
|
||||
|
||||
public void drive();
|
||||
public void stop();
|
||||
|
||||
}
|
||||
|
||||
class Car implements iVehicle {
|
||||
|
||||
public void drive() {
|
||||
print("Driving...\n");
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
print("Stopping...\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class MyCar extends Car {
|
||||
|
||||
public void drive() {
|
||||
print("Driving my car...\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Program {
|
||||
|
||||
public void driveCar(iVehicle $vehicle) {
|
||||
$vehicle->drive();
|
||||
$vehicle->stop();
|
||||
}
|
||||
|
||||
public void main() {
|
||||
object $car = new Car();
|
||||
object $mycar = new MyCar();
|
||||
$this->driveCar($car);
|
||||
$this->driveCar($mycar);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
Driving...
|
||||
Stopping...
|
||||
Driving my car...
|
||||
Stopping...
|
|
@ -0,0 +1,22 @@
|
|||
class Program {
|
||||
|
||||
string encode_ip(string $dotquad_ip) {
|
||||
string[] $ip_sep = explode('.', $dotquad_ip);
|
||||
return sprintf('%02x%02x%02x%02x', $ip_sep[0], $ip_sep[1], $ip_sep[2], $ip_sep[3]);
|
||||
}
|
||||
|
||||
string decode_ip(string $int_ip) {
|
||||
string[] $hexipbang = explode('.', chunk_split($int_ip, 2, '.'));
|
||||
return hexdec($hexipbang[0]) + '.' + hexdec($hexipbang[1]) + '.' + hexdec($hexipbang[2]) + '.' + hexdec($hexipbang[3]);
|
||||
}
|
||||
|
||||
void main() {
|
||||
string $localhost = $this->encode_ip('127.0.0.1');
|
||||
print("127.0.0.1 ==> $localhost\n");
|
||||
string $router = $this->encode_ip('192.168.2.1');
|
||||
print("192.168.2.1 ==> $router\n");
|
||||
print("$localhost ==> ", $this->decode_ip($localhost) + PHP_EOL);
|
||||
print("$router ==> ", $this->decode_ip($router) + PHP_EOL);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
127.0.0.1 ==> 7f000001
|
||||
192.168.2.1 ==> c0a80201
|
||||
7f000001 ==> 127.0.0.1
|
||||
c0a80201 ==> 192.168.2.1
|
|
@ -1,5 +1,5 @@
|
|||
final class Program {
|
||||
function main() {
|
||||
void main() {
|
||||
var_dump(function_exists('dummy_function'));
|
||||
var_dump(import('dummy'));
|
||||
var_dump(function_exists('dummy_function'));
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
class Program {
|
||||
|
||||
private int test() {
|
||||
static int $x = 9;
|
||||
return $x--;
|
||||
}
|
||||
|
||||
public void main() {
|
||||
int $a;
|
||||
do {
|
||||
$a = $this->test();
|
||||
int $z = $a;
|
||||
if($z == 6) {
|
||||
continue;
|
||||
} else if($z == 3) {
|
||||
break;
|
||||
}
|
||||
print("$z\n");
|
||||
} while($a);
|
||||
print("$a\n");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
9
|
||||
8
|
||||
7
|
||||
5
|
||||
4
|
||||
3
|
|
@ -0,0 +1,20 @@
|
|||
class Program {
|
||||
|
||||
public void main() {
|
||||
int $c = 4;
|
||||
for(int $a = 0; $a < 10; $a++) {
|
||||
for(int $b = 0; $b < 10; $b++) {
|
||||
int $c = 2;
|
||||
if($b == 2) {
|
||||
continue;
|
||||
}
|
||||
if($b == 6) {
|
||||
break;
|
||||
}
|
||||
print("Hello variables: $a $b $c\n");
|
||||
}
|
||||
}
|
||||
print("Variable \$c: $c\n");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
Hello variables: 0 0 2
|
||||
Hello variables: 0 1 2
|
||||
Hello variables: 0 3 2
|
||||
Hello variables: 0 4 2
|
||||
Hello variables: 0 5 2
|
||||
Hello variables: 1 0 2
|
||||
Hello variables: 1 1 2
|
||||
Hello variables: 1 3 2
|
||||
Hello variables: 1 4 2
|
||||
Hello variables: 1 5 2
|
||||
Hello variables: 2 0 2
|
||||
Hello variables: 2 1 2
|
||||
Hello variables: 2 3 2
|
||||
Hello variables: 2 4 2
|
||||
Hello variables: 2 5 2
|
||||
Hello variables: 3 0 2
|
||||
Hello variables: 3 1 2
|
||||
Hello variables: 3 3 2
|
||||
Hello variables: 3 4 2
|
||||
Hello variables: 3 5 2
|
||||
Hello variables: 4 0 2
|
||||
Hello variables: 4 1 2
|
||||
Hello variables: 4 3 2
|
||||
Hello variables: 4 4 2
|
||||
Hello variables: 4 5 2
|
||||
Hello variables: 5 0 2
|
||||
Hello variables: 5 1 2
|
||||
Hello variables: 5 3 2
|
||||
Hello variables: 5 4 2
|
||||
Hello variables: 5 5 2
|
||||
Hello variables: 6 0 2
|
||||
Hello variables: 6 1 2
|
||||
Hello variables: 6 3 2
|
||||
Hello variables: 6 4 2
|
||||
Hello variables: 6 5 2
|
||||
Hello variables: 7 0 2
|
||||
Hello variables: 7 1 2
|
||||
Hello variables: 7 3 2
|
||||
Hello variables: 7 4 2
|
||||
Hello variables: 7 5 2
|
||||
Hello variables: 8 0 2
|
||||
Hello variables: 8 1 2
|
||||
Hello variables: 8 3 2
|
||||
Hello variables: 8 4 2
|
||||
Hello variables: 8 5 2
|
||||
Hello variables: 9 0 2
|
||||
Hello variables: 9 1 2
|
||||
Hello variables: 9 3 2
|
||||
Hello variables: 9 4 2
|
||||
Hello variables: 9 5 2
|
||||
Variable $c: 4
|
|
@ -0,0 +1,23 @@
|
|||
class Program {
|
||||
|
||||
private int test() {
|
||||
static int $x = 9;
|
||||
return $x--;
|
||||
}
|
||||
|
||||
public void main() {
|
||||
int $a;
|
||||
int $b = 2;
|
||||
while($a = $this->test()) {
|
||||
int $b = $a;
|
||||
if($b == 6) {
|
||||
continue;
|
||||
} else if($b == 3) {
|
||||
break;
|
||||
}
|
||||
print("$b\n");
|
||||
}
|
||||
print("$b\n");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
9
|
||||
8
|
||||
7
|
||||
5
|
||||
4
|
||||
2
|
|
@ -0,0 +1,44 @@
|
|||
class Luhn {
|
||||
private string $number;
|
||||
|
||||
string getNumber() {
|
||||
return $this->number;
|
||||
}
|
||||
|
||||
void setNumber(string $number) {
|
||||
$this->number = $number;
|
||||
}
|
||||
|
||||
bool validate() {
|
||||
string $sum;
|
||||
string $revNumber;
|
||||
int $len;
|
||||
|
||||
$revNumber = strrev($this->number);
|
||||
$len = strlen($this->number);
|
||||
for(int $i = 0; $i < $len; $i++) {
|
||||
$sum += $i & 1 ? $revNumber[$i] * 2 : $revNumber[$i];
|
||||
}
|
||||
return array_sum(str_split($sum)) % 10 == 0;
|
||||
}
|
||||
}
|
||||
|
||||
class Program {
|
||||
private const NUMBERS = {'3788803280', '6487308345', '5443489710530865', '5539266155200609', '4024007151066296', '4345234978'};
|
||||
|
||||
void main() {
|
||||
int $i, $nums = sizeof($this->NUMBERS);
|
||||
object $luhn = new Luhn();
|
||||
|
||||
while($i < $nums) {
|
||||
$luhn->setNumber($this->NUMBERS[$i]);
|
||||
if($luhn->validate()) {
|
||||
print('The number ' + $luhn->getNumber() + ' has passed the Luhn validation.' + "\n");
|
||||
} else {
|
||||
print('The number ' + $luhn->getNumber() + ' has NOT passed the Luhn validation.' + "\n");
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
The number 3788803280 has passed the Luhn validation.
|
||||
The number 6487308345 has passed the Luhn validation.
|
||||
The number 5443489710530865 has passed the Luhn validation.
|
||||
The number 5539266155200609 has passed the Luhn validation.
|
||||
The number 4024007151066296 has passed the Luhn validation.
|
||||
The number 4345234978 has NOT passed the Luhn validation.
|
|
@ -0,0 +1,16 @@
|
|||
class Dog {
|
||||
|
||||
void __invoke() {
|
||||
print("I am a dog!\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Program {
|
||||
|
||||
void main() {
|
||||
object $dog = new Dog();
|
||||
$dog();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
I am a dog!
|
|
@ -0,0 +1,62 @@
|
|||
interface IntA {
|
||||
|
||||
public void test_a();
|
||||
|
||||
}
|
||||
|
||||
interface IntB {
|
||||
|
||||
public void test_b();
|
||||
|
||||
}
|
||||
|
||||
class TestA {
|
||||
|
||||
public void test_a() {
|
||||
print("Hello world from TestA::test_a().\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TestB {
|
||||
|
||||
public void test_b() {
|
||||
print("Hello world from TestB::test_b().\n");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class TestC {
|
||||
|
||||
public void test_c() {
|
||||
print("Hello world from TestC::test_c().\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TestD {
|
||||
|
||||
public void test_a() {
|
||||
print("Hello world from TestD::test_a().\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TestE {
|
||||
|
||||
public void test_b() {
|
||||
print("Hello world from TestE::test_b().\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Program extends TestE, TestD, TestC, TestB, TestA implements IntA, IntB {
|
||||
|
||||
void main() {
|
||||
$this->test_a();
|
||||
$this->test_b();
|
||||
$this->test_c();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
Hello world from TestD::test_a().
|
||||
Hello world from TestE::test_b().
|
||||
Hello world from TestC::test_c().
|
|
@ -0,0 +1,20 @@
|
|||
class Program {
|
||||
|
||||
string[] testArray() {
|
||||
return {'Machine' => 'Turing'};
|
||||
}
|
||||
|
||||
callback[] testCallback() {
|
||||
return {'callme' => void() { print("Hello world\n"); }};
|
||||
}
|
||||
|
||||
void main() {
|
||||
callback[] $constr = {'print'};
|
||||
print($this->testArray()['Machine'] + "\n");
|
||||
$this->testCallback()['callme']();
|
||||
print(true ? "TRUE\n" : false ? "true\n" : "false\n");
|
||||
(void(string $name) { print("This should work too - $name.\n");})('AerScript');
|
||||
$constr[0]('Test finished.' + "\n");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
Turing
|
||||
Hello world
|
||||
TRUE
|
||||
This should work too - AerScript.
|
||||
Test finished.
|
|
@ -0,0 +1,16 @@
|
|||
class Program {
|
||||
|
||||
void count(int $a, int $b) {
|
||||
print("Counting 2 integers: $a + $b = ", $a + $b, "\n");
|
||||
}
|
||||
|
||||
void count(float $a, float $b) {
|
||||
print("Counting 2 floats: $a + $b = ", $a + $b, "\n");
|
||||
}
|
||||
|
||||
void main() {
|
||||
$this->count(4.3, 5.7);
|
||||
$this->count(6, 4);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
Counting 2 floats: 4.3 + 5.7 = 10
|
||||
Counting 2 integers: 6 + 4 = 10
|
|
@ -0,0 +1,32 @@
|
|||
class Program {
|
||||
|
||||
string[] parsePathComponents(string $path, bool $endSlash=true, bool $base=false) {
|
||||
string[] $retArray;
|
||||
$path = trim($path);
|
||||
string $str, $temp;
|
||||
char $char;
|
||||
for(int $x = 0; $char = $path[$x]; $x++) {
|
||||
if(!strstr('/', $char)) $temp += $char;
|
||||
else if($temp) {
|
||||
$str += $temp;
|
||||
$retArray[$temp] = $str + ($endSlash ? '/' : '');
|
||||
$str += '/';
|
||||
$temp = '';
|
||||
}
|
||||
}
|
||||
($base && $temp) ? $retArray[$temp] = $str + $temp : NULL;
|
||||
return $retArray;
|
||||
}
|
||||
|
||||
void main() {
|
||||
string $path = '/my//stupid//path/to///some/file.php';
|
||||
print_r($this->parsePathComponents($path));
|
||||
|
||||
$path = 'my/other//path/';
|
||||
print_r($this->parsePathComponents($path, false));
|
||||
|
||||
$path = '/my//other/path/to///file.php';
|
||||
print_r($this->parsePathComponents($path, true, true));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
Array(5) {
|
||||
[my] =>
|
||||
my/
|
||||
[stupid] =>
|
||||
my/stupid/
|
||||
[path] =>
|
||||
my/stupid/path/
|
||||
[to] =>
|
||||
my/stupid/path/to/
|
||||
[some] =>
|
||||
my/stupid/path/to/some/
|
||||
}
|
||||
Array(3) {
|
||||
[my] =>
|
||||
my
|
||||
[other] =>
|
||||
my/other
|
||||
[path] =>
|
||||
my/other/path
|
||||
}
|
||||
Array(5) {
|
||||
[my] =>
|
||||
my/
|
||||
[other] =>
|
||||
my/other/
|
||||
[path] =>
|
||||
my/other/path/
|
||||
[to] =>
|
||||
my/other/path/to/
|
||||
[file.php] =>
|
||||
my/other/path/to/file.php
|
||||
}
|
|
@ -1,16 +1,16 @@
|
|||
class Program {
|
||||
private $s = 'monkey';
|
||||
private $t = 'many monkeys';
|
||||
private $n = 43951789;
|
||||
private $u = -43951789;
|
||||
private $c = 65;
|
||||
private string $s = 'monkey';
|
||||
private string $t = 'many monkeys';
|
||||
private int $n = 43951789;
|
||||
private int $u = -43951789;
|
||||
private char $c = 65;
|
||||
|
||||
public function main() {
|
||||
public void main() {
|
||||
$this->testMonkey();
|
||||
$this->testNumbers();
|
||||
}
|
||||
|
||||
private function testMonkey() {
|
||||
private void testMonkey() {
|
||||
printf("[%s]\n", $this->s);
|
||||
printf("[%10s]\n", $this->s);
|
||||
printf("[%-10s]\n", $this->s);
|
||||
|
@ -19,9 +19,10 @@ class Program {
|
|||
printf("[%10.10s]\n", $this->t);
|
||||
}
|
||||
|
||||
private function testNumbers() {
|
||||
private void testNumbers() {
|
||||
printf("%%b = '%b'\n", $this->n);
|
||||
printf("%%c = '%c'\n", $this->c);
|
||||
printf("%%d = '%d'\n", $this->c);
|
||||
printf("%%d = '%d'\n", $this->n);
|
||||
printf("%%e = '%e'\n", $this->n);
|
||||
printf("%%u = '%u'\n", $this->n);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
[many monke]
|
||||
%b = '10100111101010011010101101'
|
||||
%c = 'A'
|
||||
%d = '65'
|
||||
%d = '43951789'
|
||||
%e = '4.395179e+07'
|
||||
%u = '43951789'
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
class Program {
|
||||
|
||||
void add_by_ref(int &$val) {
|
||||
$val += 7;
|
||||
}
|
||||
|
||||
void main() {
|
||||
int $num = 7;
|
||||
$this->add_by_ref($num);
|
||||
var_dump($num);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
int(14)
|
|
@ -1,32 +1,32 @@
|
|||
final class Test {
|
||||
private $value;
|
||||
private int $value;
|
||||
|
||||
private function __construct() {
|
||||
private void __construct() {
|
||||
}
|
||||
|
||||
/* This is singleton */
|
||||
public function getInstance() {
|
||||
static $instance;
|
||||
public object getInstance() {
|
||||
static object $instance;
|
||||
if(!$instance) {
|
||||
$instance = new Test();
|
||||
}
|
||||
return $instance;
|
||||
}
|
||||
|
||||
public function get() {
|
||||
public int get() {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
public function set($value = 0) {
|
||||
public int set(int $value = 0) {
|
||||
$this->value = $value;
|
||||
}
|
||||
}
|
||||
|
||||
final class Program {
|
||||
public function main() {
|
||||
$testA = Test::getInstance();
|
||||
public void main() {
|
||||
object $testA = Test::getInstance();
|
||||
$testA->set(5);
|
||||
$testB = Test::getInstance();
|
||||
object $testB = Test::getInstance();
|
||||
var_dump($testB->get());
|
||||
}
|
||||
} /* class */
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
class Program {
|
||||
|
||||
string cycle(char $a, char $b, int $i = 0) {
|
||||
static char[] $switches;
|
||||
if($switches[$i])
|
||||
$switches[$i] = !$switches[$i];
|
||||
else
|
||||
!($switches[$i] = true);
|
||||
return ($switches[$i]) ? $a : $b;
|
||||
}
|
||||
|
||||
void main() {
|
||||
for(int $i = 1; $i < 3; $i++) {
|
||||
print($i + $this->cycle('a', 'b') + PHP_EOL);
|
||||
for(int $j = 1; $j < 5; $j++) {
|
||||
print(' ' + $j + $this->cycle('a', 'b', 1) + PHP_EOL);
|
||||
for(int $k = 1; $k < 3; $k++) {
|
||||
print(' ' + $k + $this->cycle('c', 'd', 2) + PHP_EOL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
1a
|
||||
1a
|
||||
1c
|
||||
2d
|
||||
2b
|
||||
1c
|
||||
2d
|
||||
3a
|
||||
1c
|
||||
2d
|
||||
4b
|
||||
1c
|
||||
2d
|
||||
2b
|
||||
1a
|
||||
1c
|
||||
2d
|
||||
2b
|
||||
1c
|
||||
2d
|
||||
3a
|
||||
1c
|
||||
2d
|
||||
4b
|
||||
1c
|
||||
2d
|
|
@ -0,0 +1,20 @@
|
|||
class Program {
|
||||
|
||||
void main() {
|
||||
int $a = 1;
|
||||
switch($a) {
|
||||
case 0:
|
||||
print("very bad\n");
|
||||
break;
|
||||
case 1:
|
||||
print("very good\n");
|
||||
case 2:
|
||||
print("good\n");
|
||||
break;
|
||||
default:
|
||||
print("bad");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
very good
|
||||
good
|
|
@ -0,0 +1,21 @@
|
|||
class Program {
|
||||
|
||||
string normalize(string $str) {
|
||||
string[] $table = {
|
||||
'Š'=>'S', 'š'=>'s', 'Đ'=>'Dj', 'đ'=>'dj', 'Ž'=>'Z', 'ž'=>'z', 'Č'=>'C', 'č'=>'c', 'Ć'=>'C', 'ć'=>'c',
|
||||
'À'=>'A', 'Á'=>'A', 'Â'=>'A', 'Ã'=>'A', 'Ä'=>'A', 'Å'=>'A', 'Æ'=>'A', 'Ç'=>'C', 'È'=>'E', 'É'=>'E',
|
||||
'Ê'=>'E', 'Ë'=>'E', 'Ì'=>'I', 'Í'=>'I', 'Î'=>'I', 'Ï'=>'I', 'Ñ'=>'N', 'Ò'=>'O', 'Ó'=>'O', 'Ô'=>'O',
|
||||
'Õ'=>'O', 'Ö'=>'O', 'Ø'=>'O', 'Ù'=>'U', 'Ú'=>'U', 'Û'=>'U', 'Ü'=>'U', 'Ý'=>'Y', 'Þ'=>'B', 'ß'=>'Ss',
|
||||
'à'=>'a', 'á'=>'a', 'â'=>'a', 'ã'=>'a', 'ä'=>'a', 'å'=>'a', 'æ'=>'a', 'ç'=>'c', 'è'=>'e', 'é'=>'e',
|
||||
'ê'=>'e', 'ë'=>'e', 'ì'=>'i', 'í'=>'i', 'î'=>'i', 'ï'=>'i', 'ð'=>'o', 'ñ'=>'n', 'ò'=>'o', 'ó'=>'o',
|
||||
'ô'=>'o', 'õ'=>'o', 'ö'=>'o', 'ø'=>'o', 'ù'=>'u', 'ú'=>'u', 'û'=>'u', 'ý'=>'y', 'ý'=>'y', 'þ'=>'b',
|
||||
'ÿ'=>'y', 'Ŕ'=>'R', 'ŕ'=>'r'
|
||||
};
|
||||
return strtr($str, $table);
|
||||
}
|
||||
|
||||
void main() {
|
||||
var_dump($this->normalize("ÿĆ Welcome ÂëÑ Žöø Ŕ"));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
string(20 'yC Welcome AeN Zoo R')
|
|
@ -0,0 +1,36 @@
|
|||
class StringTokenizer {
|
||||
private string $token;
|
||||
private string $delim;
|
||||
|
||||
public void __construct(string $str, string $delim = ' ') {
|
||||
$this->token = strtok($str, $delim);
|
||||
$this->delim = $delim;
|
||||
}
|
||||
|
||||
public void __destruct() {
|
||||
unset($this);
|
||||
}
|
||||
|
||||
public bool hasMoreTokens() {
|
||||
return ($this->token != NULL);
|
||||
}
|
||||
|
||||
public string nextToken() {
|
||||
string $current = $this->token;
|
||||
$this->token = strtok($this->delim);
|
||||
return $current;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Program {
|
||||
void main() {
|
||||
string $str = "This is:@\t\n a TEST!";
|
||||
string $delim = " !@:\t\n";
|
||||
object $st = new StringTokenizer($str, $delim);
|
||||
while ($st->hasMoreTokens()) {
|
||||
print($st->nextToken(), "\n");
|
||||
}
|
||||
unset($st);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
This
|
||||
is
|
||||
a
|
||||
TEST
|
|
@ -0,0 +1,43 @@
|
|||
class Program {
|
||||
private int $test = 7;
|
||||
|
||||
void testChar(char $value) {
|
||||
var_dump($value);
|
||||
var_dump(is_char($value));
|
||||
}
|
||||
|
||||
void testFloat(float $value) {
|
||||
var_dump($value);
|
||||
var_dump(is_float($value));
|
||||
}
|
||||
|
||||
void testObject(object $value) {
|
||||
var_dump($value);
|
||||
var_dump(is_object($value));
|
||||
}
|
||||
|
||||
void testString(string $value) {
|
||||
var_dump($value);
|
||||
var_dump(is_string($value));
|
||||
}
|
||||
|
||||
void testVoid(void $value) {
|
||||
var_dump($value);
|
||||
var_dump(is_void($value));
|
||||
}
|
||||
|
||||
void main() {
|
||||
object $objval;
|
||||
void $voidval;
|
||||
$this->testChar('c');
|
||||
$this->testChar(NULL);
|
||||
$this->testFloat(4);
|
||||
$this->testFloat(56.3);
|
||||
$this->testObject($objval);
|
||||
$this->testObject($this);
|
||||
$this->testString('sample text');
|
||||
$this->testString(NULL);
|
||||
$this->testVoid($voidval);
|
||||
$this->testVoid(NULL);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
char(c)
|
||||
bool(TRUE)
|
||||
char()
|
||||
bool(TRUE)
|
||||
float(4)
|
||||
bool(TRUE)
|
||||
float(56.3)
|
||||
bool(TRUE)
|
||||
object()
|
||||
bool(TRUE)
|
||||
object(Program) {
|
||||
['test'] =>
|
||||
int(7)
|
||||
}
|
||||
bool(TRUE)
|
||||
string(11 'sample text')
|
||||
bool(TRUE)
|
||||
string(0 '')
|
||||
bool(TRUE)
|
||||
void(NULL)
|
||||
bool(TRUE)
|
||||
void(NULL)
|
||||
bool(TRUE)
|
|
@ -1,6 +1,7 @@
|
|||
class Program {
|
||||
|
||||
function main() {
|
||||
void main() {
|
||||
mixed $foo;
|
||||
$foo = '0';
|
||||
var_dump($foo);
|
||||
$foo += 2;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
class Unicode {
|
||||
|
||||
public function unicon($str, $to_uni = true) {
|
||||
$cp = array('А' => 'А', 'а' => 'а',
|
||||
public string unicon(string $str, bool $to_uni = true) {
|
||||
string $cpp;
|
||||
string[] $cp = {'А' => 'А', 'а' => 'а',
|
||||
"Б" => "Б", "б" => "б",
|
||||
"В" => "В", "в" => "в",
|
||||
"Г" => "Г", "г" => "г",
|
||||
|
@ -33,7 +34,7 @@ class Unicode {
|
|||
"Ь" => "Ь", "ь" => "ь",
|
||||
"Э" => "Э", "э" => "э",
|
||||
"Ю" => "Ю", "ю" => "ю",
|
||||
"Я" => "Я", "я" => "я");
|
||||
"Я" => "Я", "я" => "я"};
|
||||
if($to_uni) {
|
||||
$str = strtr($str, $cp);
|
||||
} else {
|
||||
|
@ -49,8 +50,8 @@ class Unicode {
|
|||
|
||||
final class Program {
|
||||
|
||||
public function main() {
|
||||
$unicode = new Unicode();
|
||||
public void main() {
|
||||
object $unicode = new Unicode();
|
||||
var_dump($unicode->unicon("ИфйжБЦ"));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
class Program {
|
||||
private $概要 = "AerScript Interpreter";
|
||||
private string $概要 = "AerScript Interpreter";
|
||||
|
||||
public function main() {
|
||||
public void main() {
|
||||
$this->ダウンロード();
|
||||
var_dump($this->概要);
|
||||
var_dump($this->isUTF8('hello'));
|
||||
var_dump($this->isUTF8("すが、基本的な使い方は単純です。かしながら使い方を身につけていきましょう"));
|
||||
}
|
||||
|
||||
private function ダウンロード(){
|
||||
private void ダウンロード(){
|
||||
print($this->概要 + "\n");
|
||||
}
|
||||
|
||||
private function isUTF8($str) {
|
||||
$b = 0;
|
||||
$c = 0;
|
||||
$bits = 0;
|
||||
$len = strlen($str);
|
||||
for($i = 0; $i < $len; $i++) {
|
||||
private bool isUTF8(string $str) {
|
||||
int $b = 0;
|
||||
int $c = 0;
|
||||
int $bits = 0;
|
||||
int $len = strlen($str);
|
||||
for(int $i = 0; $i < $len; $i++) {
|
||||
$c = ord($str[$i]);
|
||||
if($c >= 128) {
|
||||
if(($c >= 254)) return false;
|
||||
|
|
Loading…
Reference in New Issue