sqfvm / runtime Goto Github PK
View Code? Open in Web Editor NEWCustom implementation of the Arma script language SQF
License: GNU Lesser General Public License v3.0
Custom implementation of the Arma script language SQF
License: GNU Lesser General Public License v3.0
Describe the bug
When pasting a piece of code in the VM which contains empty lines, it will only execute the part till the first empty line.
To Reproduce
Steps to reproduce the behavior:
test_fnc_print = {
params ["_value"];
diag_log(format ["%1", _value]);
};
["some test"] call text_fnc_print;
[WORK] <ARRAY> ["some test"]
test_fnc_print = {
params ["_value"];
diag_log(format ["%1", _value]);
};
["some test"] call text_fnc_print;
[WORK] <EMPTY>
Expected behavior
I would expect that "any" code, with or without empty lines (for readability) are executed properly.
Additional context
Tested with 1.3.1-RC1 (Win64.x64)
{
diag_log [_i];
_i = 123;
} foreach [1,2,3]
Result:
[DIAG] [nil]
[DIAG] [123]
[DIAG] [123]
[WORK] <EMPTY>
Expected:
[DIAG] [nil]
[DIAG] [nil]
[DIAG] [nil]
[WORK] <EMPTY>
Variable scope is destroyed after each iteration. all variables should be gone.
createMarker ["xyz", [0,0]]
[1,[2,[3]]] isEqualTo [1,[2,[3]]]
returns false,
although it's supposed to return true according to the wiki page.
Expected behaviour:
for "_i" from 0 to 1 do
{
assert (_i == 0);
if true exitWith {};
};
local _i = 0;
while { true } do
{
assert (_i == 0);
_i = _i + 1;
if true exitWith {};
};
init.sqf:
diag_log "including test.hpp";
#include "test.hpp"
test.hpp:
diag_log "in test.hpp: checking test_init";
if(isNil "test_init") then {
diag_log "test_init is nil, calling test.sqf";
call compile preprocessFileLineNumbers "test.sqf";
};
test.sqf:
diag_log "in test.sqf: test_init set to true";
test_init = true;
#include "test.hpp"
Arma rpt reads:
22:19:43 "including test.hpp"
22:19:43 "in test.hpp: checking test_init"
22:19:43 "test_init is nil, calling test.sqf"
22:19:43 "in test.sqf: test_init set to true"
22:19:43 "in test.hpp: checking test_init"
SQF-vm repeats forever:
...
[DIAG] in test.hpp: checking test_init
[DIAG] test_init is nil, calling test.sqf
[DIAG] in test.sqf: test_init set to true
[DIAG] in test.hpp: checking test_init
Describe the bug
The config parser throws a "Missing curly closing bracket" error if a number, in an array, starts with a decimal point.
To Reproduce
configparse__ "class A { a[]={ .1 }; };"
}
).Expected behavior
No error.
Screenshots
N/A
Additional context
N/A
Describe the bug
The config parser errors when parsing a GUI's controls[]
.
To Reproduce
test.cpp
, containing:class My_Dialog {
controls[] = { My_Text_1 };
class My_Text_1 {};
};
sqfvm.exe --parse-only --input-config test.cpp
[ERR] [L2|C16|file] Missing curly closing bracket (`}`).
[ERR] [L2|C16|file] Expected Statement termination using `;`.
[ERR] [L2|C26|file] Missing equal sign (`=`).
Expected behavior
No error.
Screenshots
N/A
Additional context
N/A
Describe the bug
Unexpected IFNDEF. Already inside of a IFDEF or IFNDEF enclosure.
is received when an include
, containing a ifdef
/ifndef
, is wrapped with a ifdef
/ifndef
.
To Reproduce
include.sqf
, containing:#ifndef UNDEFINED
systemChat "Foo";
#endif
#ifndef UNDEFINED
#include "include.sqf"
#endif
Unexpected IFNDEF. Already inside of a IFDEF or IFNDEF enclosure.
Expected behavior
No error when if(n)def is used inside of an include
file, wrapped in a if(n)def.
Additional context
N/A
fn = {
params [["_val", "", [""]]];
isNil "_val"
};
[] call fn;
Should return false, but returns true. _val should take default value of "" and isNil should therefore return false.
This works correctly when the accepted type list is removed (params [["_val", ""]];
)
To Reproduce
Preprocess this:
"a test\
"
Actual output:
"a test\
"
Expected output:
"a test"
Preprocess this:
diag_log 'a';\
diag_log 'b';
Actual output:
diag_log 'a';\
diag_log 'b';
Expected output:
diag_log 'a';diag_log 'b';
allSimpleObjects is treated as a nular even tho it's a unary.
Right arg is an array: https://community.bistudio.com/wiki/allSimpleObjects
lSimpleObjects ["hello"]; ^ [ERR][L2|C17|__libraryfeed.sqf] Expected either ';' or ','.
e.g. __SQFVM__
or something. This will help with working around missing commands, changing behavior such that it makes sense for running "headless" etc.
Does not work:
#define VAL 1
#define LOG_MACRO(b) diag_log str(b)
LOG_MACRO( (1 == VAL) );
Works:
#define VAL 1
#define LOG_MACRO(b) diag_log str(b)
LOG_MACRO( 1 == VAL );
Describe the bug
If a file is included multiple times, Recursive include detected. Include Tree.
is received.
To Reproduce
include.sqf
#include "include.sqf"
#include "include.sqf"
Recursive include detected. Include Tree.
Expected behavior
No error thrown when including the same file, multiple times.
Screenshots
N/A
Additional context
N/A
Expected behaviour:
assert (str 0.5 == "0.5");
assert (format ["%1", 0.5] == "0.5");
Currently, regressions are only found when they "appear"
to counteract this, proper testing should be done.
For this, a proper testing mechanism needs to be implemented into the cmake process.
Required testing components for now:
Describe the bug
Config parser doesn't support external base classes.
To Reproduce
config.cpp
, containing:class externalBaseClass;
class myClass: externalBaseClass {};
sqfvm.exe -a --parse-only --input-config config.cpp
Expected behavior
No error when using external base classes.
Screenshots
N/A
Additional context
N/A
To Reproduce
Preprocess this:
'/*test*/'
Actual output:
''
Expected output:
'/*test*/'
fn_a = {
true
};
fn_b = {
params ["_ignore"];
true
};
// works
val = [] call (if([] call fn_a) then { fn_a } else { fn_a });
// doesn't work, only difference is that fn_b has params
val2 = [] call (if([true] call fn_b) then { fn_a } else { fn_a });
val2 = [] call (if([true] call fn_
^^^^
[WRN][12|C6] callBinary could not receive a value for left arg.
[WORK] <ARRAY> []
Describe the bug
Using foreach around a switch containing the case clauses will cause the variable tree to loose the _forEachIndex variable.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
2. Output should resemble _testarray
Additional context
private _testarray = [1, 2, 3, 4 ,5, 6];
private _a = 3;
switch (_a) do
{
{
case _x: { hint str (_testarray select (_forEachIndex + 1)) };
} foreach _testarray
};
Describe the bug
While writing this test, I had the wrong result flag (true instead of false)
https://github.com/SQFvm/vm/blob/master/tests/sqf/namespace.sqf#L12
And it printed this:
[CHAT] SYSTEM: Test !FAILED! '\sqf\namespace.sqf' - 8 { missionNamespace getVariable [false, "don'texist"] }
The code is
{ missionNamespace getVariable ["don'texist", false] }
But the ASM->SQF conversion printed
{ missionNamespace getVariable [false, "don'texist"] }
instead. Swapping the array entries.
To Reproduce
Steps to reproduce the behavior:
Change https://github.com/SQFvm/vm/blob/master/tests/sqf/namespace.sqf#L12
to
["assertEqual", { missionNamespace getVariable ["don'texist", false] }, true],
and watch the test error
Repository should be split up into:
That way, everyone may pick the part he likes the most/wants to replace.
Useful Links:
To create a test case, create another file like this: https://github.com/SQFvm/vm/blob/master/tests/sqf/select.sqf at https://github.com/SQFvm/vm/blob/master/tests/sqf/
Parsing produces error reports with file name on the next line, but in execution file name is missing. Ideally please have a standardized one line error format so IDEs (and simple regex) can pick it up.
e.g. https://blogs.msdn.microsoft.com/msbuild/2006/11/02/msbuild-visual-studio-aware-error-messages-and-message-formats/
Visual Studio Code can support a number of different formats out of the box as seen here: https://code.visualstudio.com/docs/editor/tasks#_processing-task-output-with-problem-matchers
Describe the bug
The config parser throws a "Missing curly closing bracket" error, if there is no whitespace between the block content semicolon and closing curly brace.
To Reproduce
configparse__ "class A {a=1;};"
}
).configparse__ "class A {a=1; };"
Expected behavior
No error.
Screenshots
N/A
Additional context
N/A
Sometimes absolute, sometimes relative. They should be consistent, either always relative or always absolute, not a mixture, regardless of how the path was introduced to the compiler.
This helps with parsing and reading.
[ERR][L338|C8|OOP_Light\OOP_Light_init.sqf] Expected either ';' or ','.
E__, __LINE__] call OOP_assert_cla
^^^^
[RNT][L11|C249|c:\Users\billw\Documents\Arma 3\mpmissions\CmdrAITestbed.Altis\scripts\RefCountedTest.sqf] callBinary could not receive a value for right arg.
[WORK] <ARRAY> ["RefCounted",nil,nil]
#define MACRO() []
#define MACRO2(a, b) private a = b
MACRO2(_a, MACRO());
ate _a = MACRO);
^
[ERR][L3|C17|__libraryfeed.sqf] Reached EOF before finishing parsing.
[WORK] <EMPTY>
#define MACRO(a) a
#define MACRO2(a, b) private a = b
MACRO2(_a, MACRO(0));
private _a = 0;
^
[RNT][L3|C12|__libraryfeed.sqf] [ERR][L3|C8|__libraryfeed.sqf] Arg Count Missmatch.
[WORK] <SCALAR> 0
Is your feature request related to a problem? Please describe.
I would love to run Unit Tests very easily against the SQFvm
Describe the solution you'd like
Best case I just refer to my SQF sources and test files and then magic happens
Describe alternatives you've considered
no alternatives accepted
Additional context
Starting ArmA3 only to see if my unit tests go green is a big time waster. SQFvm could be the best thing existing if a testing engine would be available!
Describe the bug
The config parser inconsistently throws an unexpected "Missing equal sign" error for classes.
To Reproduce
configparse__ "class A {};"
a few times.=
).Expected behavior
No error.
Screenshots
N/A
Additional context
N/A
// Should create a warning because unused
is not being used in the macro but present in the define
#define foo(unused) bar
foo(something)
// Should not create a warning as define contents are empty
#define foo(unused)
foo(something)
@SQF#3423
#define QUOTE(x) #x
#define QGVAR(x) QUOTE(ace_test_##x)
#define HIT_STRUCTURAL QGVAR($#structural)
HIT_STRUCTURAL
Actual:
[WORK] <STRING> ace_test_##$#structural
Expected:
[WORK] <STRING> ace_test_$#structural
Describe the bug
--virtual
's virtual path is case-sensitive
To Reproduce
test.cpp
, containing #include "\A3\3den\ui\macros.inc"
sqfvm.exe --parse-only --virtual "P:\a3|a3" --input-config test.cpp
Failed to include '\A3\3den\ui\macros.inc'
sqfvm.exe --parse-only --virtual "P:\a3|A3" --input-config test.cpp
Expected behavior
Virtual path to be case-insensitive.
Screenshots
N/A
Additional context
N/A
To allow commands like preprocessFile
to return what files they processed and thus let compile know where a given instruction is located at, the #file
instruction should be placed at the very start of every file (unless the path is not provided).
Commas within strings passed to macros will cause the count to be wrong and generate "Arg Count Missmatch".
Repro:
#define MACRO_TEST(a, b, c)
MACRO_TEST("this is a comma, test", 1, 2);
#define LOG(x) diag_log [x, FILE, LINE];
LOG(a)
LOG(a)
LOG(a)
Actual:
[DIAG] [nil,"__libraryfeed.sqf",1]
[DIAG] [nil,"__libraryfeed.sqf",1]
[DIAG] [nil,"__libraryfeed.sqf",1]
Expected:
[DIAG] [nil,"__libraryfeed.sqf",3]
[DIAG] [nil,"__libraryfeed.sqf",4]
[DIAG] [nil,"__libraryfeed.sqf",5]
Or
macro.hpp:
#define LOG(x) diag_log [x, FILE, LINE];
script.sqf:
#include "macro.hpp"
LOG(a)
LOG(b)
Actual:
[DIAG] [nil,"macro.hpp",1]
[DIAG] [nil,"macro.hpp",1]
Expected:
[DIAG] [nil,"script.sqf",2]
[DIAG] [nil,"script.sqf",3]
Expected behaviour:
local _i = 0;
for "_" from 0 to 1 step 0 do
{
_i = _i + 1;
if (_i == 2) exitWith {};
};
assert (_i == 2);
Describe the bug
All of the trigonometric functions (cos, tan, sin, etc) in SQF-VM are backed by the underlying C++ std library functions of the same name.
However, C++ uses radians exclusively for parameters + return values, whereas Arma 3 uses degrees.
SQF-VM needs to convert degrees to radians before passing it to the underlying std:: functions.
To Reproduce
Steps to reproduce the behavior:
sin 30
in SQF-VM. Correct value is 0.5, actual value is not.Expected behavior
sin 30
takes degrees, and returns 0.5.
Additional context
Affected operators are (in order of appearance in ops_math.cpp)
#define DOUBLES(var1,var2) var1##_##var2
#define PREFIX ace
#define COMPONENT medical_engine
#define ADDON DOUBLES(PREFIX,COMPONENT)
#define GVAR(var1) DOUBLES(ADDON,var1)
#define QUOTE(x) #x
#define QGVAR(var1) QUOTE(GVAR(var1))
#define HIT_STRUCTURAL QGVAR($#structural)
[HIT_STRUCTURAL, 0]
Actual:
["ace_medical_engine_$"tructural"", 0]
dical_engine_$"tructural"", 0]
^^^^^^^^^
[ERR][L9|C23|P:\x64\__commandlinefeed.sqf] Expected ']'.
dical_engine_$"tructural"", 0]
^^^^^^^^^
[ERR][L9|C23|P:\x64\__commandlinefeed.sqf] Expected either ';' or ','.
ine_$"tructural"", 0]
^
[ERR][L9|C32|P:\x64\__commandlinefeed.sqf] Expected either ';' or ','.
Executing...
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
[WORK] <EMPTY>
Expected:
["ace_medical_engine_$#structural", 0]
Describe the bug
Verbose config parsing outputs "Exiting due to error." when no error occurs and doesn't output it when an error occurs.
To Reproduce
test.cpp
, containing class A {}
sqfvm.exe --verbose --parse-only --input-config test.cpp
Exiting due to error.
is displayed.test.cpp
to class A {
Exiting due to error.
.Expected behavior
"Exiting due to error." outputted when an error occurs, instead of when none occur.
Screenshots
N/A
Additional context
runtime/src/parser/config/default.h
Line 119 in ab57250
{
private "_x";
diag_log [_x];
} foreach [1,2,3]
Result:
[DIAG] [nil]
[DIAG] [nil]
[DIAG] [nil]
Expected:
[DIAG] [1]
[DIAG] [2]
[DIAG] [3]
I played around with your tool and well found it pretty cool for hacking some sqf scripts while on the run. But I am missing the use of commands and functions like findNearestEnemy
.
I was tinkering in my head if it might be a solution if we have to provide some kind of mocked function list. For instance consider this mock-function.sqfmock
fictional file (I am scripting for a month - please don't judge my syntax):
var mockedUnits = createGroup west; // create a mockedUnits group
var mockedFoundEnemy = mockedUnits createUnit [type, position, markers, placement, special] // setting right parameters
_ findNearestEnemy _ >> mockedFoundEnemy // tell the function with >> to return the given object regardless of the parameters given (type, etc.)
Explaination
The first two lines are the test objects that have to be created because findNearestEnemy
should return the mockedFoundEnemy
regardless with what parameters the function is called ( the _
indicates a wildcard for parameters)
So after "loading" this mock-function.sqfmock
into the CLI I can run the following within the REPL
// objects defined before this
someObject findNearestEnemy somePosition;
And the REPL will return the mockedFoundEnemy
object. This way I am able to write my functions and use these commands and BIS functions. Implied that this mock-function.sqfmock
has the needed functions mocked which is a good piece of work - but hey - maybe a community could kind of contribute to a huge mock file.
I hope you understand what I mean
PS: The idea and syntax is inspired by the Java Spock Testing Framework
1 based is the standard in code line error reporting I believe.
It is the last issue stopping my Visual Studio Code compile task from correctly populating the problems tab!
Describe the bug
Seems like switch always returns nil, but it should return the value that the last case/default returned.
To Reproduce
_taskFunction = {
case 1: {"a"};
case 2: {"b"};
case 3: {"c"};
};
_value = switch 2 do {
call _taskFunction;
default {"default"}
};
_value
Expected:
[WORK] "b"
Actual:
[WORK] <EMPTY>
_taskFunction = {
case 1: {"a"};
case 2: {"b"};
case 3: {"c"};
};
_value = switch 2 do {
call _taskFunction;
default {"default"}
};
hint _value;
_value
Expected:
[HINT] b
Actual:
[RNT][L12|C0|__libraryfeed.sqf] callUnary could not receive a value for right arg.
Stacktrace:
1: namespace: missionNamespace scopename: callstack: callstack
[STT][L12|C0|__libraryfeed.sqf]
[WORK] <EMPTY>
private _y = missionNameSpace getVariable "blah";
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[RNT][1|C10] assignToLocal could not receive a value.
To Reproduce
Preprocess this:
/*
*//*test*/
Actual output:
/*test*/
Expected output:
Arma is only using
#line 123 some/file/path.sqf
instead of
#file some/file/path.sqf
#line 123
Expected behaviour:
for "_i" from 0 to -1 do { assert false };
for "_i" from -1 to 0 step -1 do { assert false };
isNil {};
This will stop further execution. It works in Arma (we use it for emulating a critical section).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.