Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[VSCRIPT] Class defined in the script' scope is not accessible in another class in the same scpoe #173

Closed
VZhelev opened this issue Jan 20, 2022 · 2 comments
Labels
Bug Something isn't working VScript Mapbase - Involves VScript

Comments

@VZhelev
Copy link

VZhelev commented Jan 20, 2022

Description

I found a strange behavior of the execution context in a script.
The following example works fine when it is executed directly in squirrel 3.1, but it fails when it is executed in the game with the following message AN ERROR HAS OCCURRED [the index 'Point' does not exist]

Steps to reproduce

Steps to reproduce the strange behavior:

  1. Have a .nut script that has the following code:
class Point {
	x = null;
	y = null;

	constructor(_x, _y) {
		x = _x;
		y = _y;
	}
}

class Rectangle {
	topLeftPoint = null;
	bottomRightPoint =  null;

	constructor() {
		topLeftPoint = Point(0, 0);
		bottomRightPoint = Point(100, 100);
	}
}

rectangle <- Rectangle();
  1. Craete a map that references our script by logic_script entity and run the map.
  2. See the following error in the console AN ERROR HAS OCCURRED [the index 'Point' does not exist]

Expected behavior

The expected behavior is to run the map and the Rectangle class is successfully instantiated.

Additional context, that may help for better understanding the problem

After hours of reading, debugging and testing I reproduce the same error in pure squirrel (v3.1), and it looks like the core of the problem should be in the execution context.

  1. Reproduced in Squirrel v3.1 - Nested execution context
CustomScope <- {}
class CustomScope.Point {}
class CustomScope.Circle {
	position = null;
	constructor() {
		// Here the Point does not exists either in current environment (this) and root table(::).
		// It exists ony in the CustomScope table
		position = Point(0, 0);
	}
}
function CustomScope::Run() {
	// Here the Point and Circle exists, because the current environment(this) is the CustomScope.
	local point = Point(); 
	local circle = Circle();
}
CustomScope.Run();
  1. Reproduced in Squirrel v3.1 - Execute a file in nested execution context
## execution code
CustomScope <- {}
function CustomScope::Run() {
	dofile("file-to-include.nut"); // load, compile and execute a code in the CustomScpoe execution context
}
CustomScope.Run();
## file-to-include.nut
class Point {}
class Circle {
	position = null;
	constructor() {
		// Here the Point does not exists either in current environment (this) and root table(::).
		// It exists ony in the CustomScope table
		position = Point(0, 0);
	}
}
// Here the Point and Circle exists, because the current environment(this) is the CustomScope.
local point = Point(); 
local circle = Circle();
  1. Tested in Mapbase VScript - Workaround for the issue
// define the script's scope in the root table, in order to access it in any execution context
::MyScriptScope <- this;

class Point {
	x = null;
	y = null;

	constructor(_x, _y) {
		x = _x;
		y = _y;
	}
}

class Rectangle {
	topLeftPoint = null;
	bottomRightPoint =  null;

	constructor() {
                // access the Point class by accessing the MyScriptScope, which is defined in the root table
		topLeftPoint = ::MyScriptScope.Point(0, 0);
		bottomRightPoint = ::MyScriptScope.Point(100, 100);
	}
}

rectangle <- Rectangle();
printl(rectangle);
@VZhelev VZhelev added Bug Something isn't working VScript Mapbase - Involves VScript labels Jan 20, 2022
@VZhelev VZhelev changed the title [VSCRIPT] [VSCRIPT] Class defined in the script' scope is not accessible from another class Jan 20, 2022
@VZhelev VZhelev changed the title [VSCRIPT] Class defined in the script' scope is not accessible from another class [VSCRIPT] Class defined in the script' scope is not accessible in another class in the same scpoe Jan 20, 2022
@samisalreadytaken
Copy link

samisalreadytaken commented Jan 20, 2022

This is the expected behaviour. The scope your script is running is not a delegate to your classes for them to fallback to, but every context falls back to the root table (since Squirrel 3.0).

Scripts executed inside entities are placed in a table in the root table. Assume T is the entity scope, A, B, C and D are defined inside your script file.

::printl <- function(s) { print( s + "\n" ) }

::T <-
{
	A = {}
	B = { function fn() { printl( A ) } }

	C = class {}
	D = class { function fn() { printl( C ) } }
}

There are no delegations here. A and B are independent tables, C and D are independent classes. They can only access themselves and the root. T.B.fn() and T.D.fn() will fail because they don't see other variables inside T.

For tables to access their 'siblings' inside T, you need to define T as their delegate.

A <- {}
B <- { function fn() { printl( A ) } }.setdelegate( this )

Now B.fn() will work.

For classes, you will have to inherit, and access the base class with base.

C <- class {}
D <- class extends C { function fn() { printl( base ) } }

Class inheritance is more restrictive, so you can simply declare the variables they need to access using local. The solution to your problem becomes:

class Point {}
local Point = Point;

class Rectangle
{
	constructor()
	{
		printl( Point() )
	}
}

Or alternatively reference the other class in a member variable:

class Point {}

class Rectangle
{
	Point = Point;

	constructor()
	{
		printl( Point() )
	}
}

Mapbase's implementation is only about how the engine accesses the Squirrel VM. The language itself is not any different.

@VZhelev
Copy link
Author

VZhelev commented Jan 20, 2022

Thank you for the clarifications and examples.
They really helped me to understand better what's going on.

@VZhelev VZhelev closed this as completed Jan 20, 2022
samisalreadytaken pushed a commit to samisalreadytaken/source-sdk-2013 that referenced this issue Jan 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something isn't working VScript Mapbase - Involves VScript
Projects
None yet
Development

No branches or pull requests

2 participants