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

The switch statement evaluates its expression multiple times #2049

Closed
CornerPin opened this issue May 5, 2020 · 8 comments · Fixed by #2555
Closed

The switch statement evaluates its expression multiple times #2049

CornerPin opened this issue May 5, 2020 · 8 comments · Fixed by #2555
Labels

Comments

@CornerPin
Copy link
Contributor

CornerPin commented May 5, 2020

The switch statement expression is evaluated for every comparison.

Calls = 0

if (first()) {
    function number rand3() {
        Calls++
        return randint(3)
    }
}

switch (rand3()) {
    case 1,  print("Case 1") break
    case 2,  print("Case 2") break
    case 3,  print("Case 3") break
    default, print("Default") # Should never print
}

print("Calls: " + Calls + "\n")

interval(1000)

Outputs:

Default
Calls: 3

Default
Calls: 3

Case 3
Calls: 3

Case 2
Calls: 2

Default
Calls: 3

Case 1
Calls: 1

Case 3
Calls: 3
@Divran
Copy link
Contributor

Divran commented May 5, 2020

Hmm, I'm not sure how to go about fixing that. @thegrb93 , any ideas?

edit: relevant code https://github.com/wiremod/wire/blob/master/lua/entities/gmod_wire_expression2/base/compiler.lua#L877-L914

@thegrb93
Copy link
Contributor

thegrb93 commented May 5, 2020

I'm guessing this is getting the rand3 function, https://github.com/wiremod/wire/blob/master/lua/entities/gmod_wire_expression2/base/compiler.lua#L881

and then this is evaluating it? https://github.com/wiremod/wire/blob/master/lua/entities/gmod_wire_expression2/base/compiler.lua#L902

We need to move its evaluation to before checking each case, and check each case with that result. I have no idea how E2 stack works though.

@thegrb93
Copy link
Contributor

thegrb93 commented May 5, 2020

In other words, we just need https://github.com/wiremod/wire/blob/master/lua/entities/gmod_wire_expression2/base/compiler.lua#L881 to fully evaluate the expression inside of it.

@Divran
Copy link
Contributor

Divran commented May 5, 2020

I think I may have fixed it. I don't know if this is the 'proper' way to do it though

function Compiler:InstrSWITCH(args)
	-- args = { "switch", trace, value expression, { { case expression or nil, body }... } }
	-- up to one case can have a nil case expression, this is the default case
	self:PushPrfCounter()
	local val, type = self:EvaluateStatement(args,1) -- This is the value we are passing though the switch statement
	local prf_cond = self:PopPrfCounter()

	-- build table which ensures the value is only evaluated one time
	local value = {
		function(self, args)
			if not args.evaluated then
				args.evaluated = val[1]( self, val )
			end

			return args.evaluated
		end
	}

	[...]

@bigdogmat
Copy link
Member

bigdogmat commented May 5, 2020

I don't think there is a proper way to do this. A less hacky way might involve assigning the value to a hidden global then accessing it (e.g. delta), not to say that would be better.

@Divran
Copy link
Contributor

Divran commented May 5, 2020

that seems like more hacky to me. keep in mind that the "args" table I'm saving it to right there is the "value" table.

local value = { <-- value table here and
		function(self, args) <-- args table here, are both the same exact table

@Divran
Copy link
Contributor

Divran commented May 5, 2020

I also dunno if it properly resets itself through executions. Will this code evaluate one time and then never again for the whole lifetime of the e2? it might.

@bigdogmat
Copy link
Member

Will this code evaluate one time and then never again for the whole lifetime of the e2?

Yes, it'll have to be reset inside the switch operator function. I proposed mine cause it doesn't require fakey statements

Vurv78 added a commit to Vurv78/wire that referenced this issue Mar 21, 2023
Final tweaks on switch case working. This would also resolve wiremod#2049 since operators take the actual values as arguments rather than instructions.
@Vurv78 Vurv78 mentioned this issue Apr 5, 2023
3 tasks
Vurv78 added a commit that referenced this issue Oct 1, 2023
* Initial attempt

* Sync

* Sync

* First functional prototype

* Removed ast.lua file (Largely useless)
* Removed optimizer.lua (Will be reimplemented with the new compiler as a step later.)
* Documented more parser changes
* Make tokenizer behave backwards-compatibly again
* Delete Compiler and Reimplement
* Removed syranide credit since E2 has been largely completely rewritten by me and wireteam/contributors

With just ~300 LOC the new compiler can already handle for loops, if statements and function calls. I just need to implement the rest of the functionality and make functions backward compatible.

* More changes

* Reworked preprocessor to also return multiple errors, and to use the new trace/error system.

* Added multi-error support to the editor

* All compiler steps now return errors in the form of the "Error" struct. Even E2Lib.errorHandler now will return one.

* Made wire_expression2_reload also reload the compiler and E2Lib.

* Work on backwards compatibility for registerFunction, registerOperator, registerType, etc functions. These are being deprecated for a future better extension api that won't need any preprocessing.

* Optimization: Only check for continue and break when inside a loop

* Add more compiler instruction support (Try, Function, Arithmetic, etc). Still need to deal with handling variables aot to avoid runtime scoping.

* Pass test suite

* wire_expression2_validate -> E2Lib.Validate
* removed more useless operator internals

Passing test suite doesn't really mean anything because it only tests the parsing part really well. It isn't comprehensive considering all tests pass despite me not having implemented variable scoping at runtime nor index assignment.

* Reimplement prf checks & Variadic params

* Reimplemented perf checks, probably not 1:1 but it works.

* Fixed lua error when the e2 editor was loading extensions

* Fix calling E2Lib.Compiler.Execute incorrectly in E2Lib.Validate

* Reimplemented variadic parameters

* Fix methodcall and legacy case

* If attributes not specified in `registerFunction`, automatically add and mark as legacy.

* Fix methodcall not properly taking arguments

* Make parser arguments function faster and more concise

* Many changes

* Moved ScopeManager into the e2lib
* Implement key value constructors for array and table
* Implement index get operator (no backwards compat)
* Reimplement index get operator for table and array, lower op cost (1 op for arrays, 3 for table from 5 for both.)
* Auto-mark registerOperator functions as legacy same as functions
* Add check for self.registered_events in destructor in case compilecode isn't called for whatever reason.
* Remove unused DefineLocal node variant
* Implement more helpful error message for (=) in expression.
* Reimplement includes

A lot closer to functional, still very far though.

* Fix runtime error detection

* Inject trace into state every sequence

Sad runtime performance hit, maybe in the future there could be a system for fallibility so it only injects when doing something potentially fallible

* Fix e2test runtime errors

* Too many changes

* Implemented indexing assignment
* Implemented runtime scoping
* Partially-implemented events
* Rewrote array setters
* Fix assignment to another identifier
* Fix global variable initialization on E2 start (persist/io)
* Remove unused / redundant / now unsupported operators from extpp
* Make table setter/getters cost less ops

I need to reimplement all the warnings I added, and a check for variadic syntax sugar to ensure arrays aren't passed into array varargs.

Also there's a weird parsing issue with doing X = X + 1. (X = 1 + X works)

* Runtime changes

* Replace ScopeManager with RuntimeContext class (now shared with makeContext function

* Remove now redundant assignment operators. Need to come up with a solution for special table-like types, though.

* Removed and/or/neq/not operators, since they are redundant and can be done internally using the "is" operator.

* Fixed printing of arrays to not be garbage (Doesn't break on empty arrays, and much faster using table.concat)

* Removed "delta" functionality, it's slow, useless, and I have no idea why anyone would ever want this, and probably nobody will notice it was removed.

* Rewrote a good amount of operators from the preprocessor syntax to the new registerOperator arguments. All operators will have to be rewritten, functions will keep backwards compatibility since we can't expect extension developers to rewrite everything.

* Fixed parser issue when assigning an identifier

* Fixed parser issue when using an identifier in certain cases

There's still an issue with doing X = X + 1 (wtf)

* Make for loop and while loop iterations only cost 1 / 20 ops per iteration (base cost). This is just the cost of an empty block. It's added to the cost of what's in the actual block so it's fine to be this low. It also means now E2 can run an empty for loop to ~400k numbers at base quota.

* Reimplement legacy op support, Runtime changes

* Reimplement support for legacy operators for certain operations

* Mark new numeric operators as nonlegacy

* Remove "delta" use from vector equal

* Delete unnecessary != operator from vector

* Remove unnecessary push and pop scopes on execute (Should start on scope 0 anyway.)

* Fix parse error when doing X = Y + 1

* Fixes

* Fixed hopefully final issue parsing assignments

* Change opcost of print functions (lower normal ones, raise driver/color ones)

* Port string operators to new api (and fix some functions that could be abused)

* Fixed inputs/outputs

* Mark ported angle operators as nonlegacy

* Add variadic unit test

* More fixes

* Fixed outputs not using correct wire_expression_types table
* Tidy include and preprocessor code
* Fix recursion typing
* Fix an issue from creating an error message concatenating a void returning function's return

* Parity (Awfulness)

* Disallow user functions overriding lua functions
* Disallow overriding user functions with functions that return differing types
* Fix "is" operator by marking as nonlegacy
* Fix string calls implementation (ew)
* Fix function recursion by reimplementing the old isolated scope system (ew)
* Fix error when assigning to void expression (ew)
* Only allow incrementing/decrementing number types

* Fix local declaration and increment/decrement

* Local declaration now has its proper special case so it isn't being treated as an assignment

* Increment/Decrement lookup a variable's scope rather than only looking in the current scope

* Fix case of indexing breaking parsing

Fixed issue where if you had a methodcall or stringcall after an index it'd fail to parse

* Multiple fixes

* Fix wirelinks (Rewrite operators with new system)

* Remove nodiscard from runOnTick

* Rewrite string idx operator to new system

* Fix some incomplete parsing

* Don't allow void functions to be used as an expression (Separate CompileNode into CompileExpr and CompileStmt)

* Rewrite foreach

* Removed "fea" operator for new "iter" operator, which is much simpler and doesn't require the end user to manage executing the E2.

* Rewrote foreach operations to use "iter" operator.

* Support data indexing clks

* Fix and operation (was being called incorrectly)
* Remove all assignment operators
* Support mutable data type clks
* Remove all != operators (now redundant, uses == operator internally.)
* Port wirelink index setters getters to new system

* Switch case support

Final tweaks on switch case working. This would also resolve #2049 since operators take the actual values as arguments rather than instructions.

* Fix a unit test

* Implement unary wire operators

Removed their operators (registerOperator) and are now implemented in the compiler.

* Kill `wire_expression2_delta`

Thank fuck

Also made a ton more branches for and/or operators for mixing with legacy operations.. awful..

* Fix strict and 2420 unit tests

* Fixed writing error message to wrong scope
* Fixed 2420 regression test erroring because of the e2lib emulation function pushing a scope before running the code (as E2 used to do)

* Fix function scoping at compile time

When you had a function nested somewhere since it wasn't isolating the scope (like it does at runtime) it was indexing the wrong location for the function parameters.

Also made events do this

* Fix methodcall passing function for method

* Fix indexing assignment parsing and compilation

* Replace "idx" operator with new "indexset" and "indexget" operators since I don't plan on supporting backwards compatibility for it anyway.

Addons don't really make types that use it so this shouldn't be a problem.

* Removed kvarray and kvtable operators since they're implemented in the compiler now.

* Removed operator[] and operator[T] extpp support

* Removed remaining use of `delta` in quaternion, entity, complex, bone libraries

* Ops changes + operator_is -> "is"

* Port uses of operator_is syntax to registerOperator("is"). I don't want to provide backwards compat for it but I might have to, granted it'll be through the preprocessor.

* Don't add cost of statements in loop ops (Because the block itself already adds that to the current prf.) Also made all costs 1 / 20. Foreach is the outlier which costs slightly more at 1 / 15.

* Remove sudo legacy support from not operator (pointless since legacy "is" wasn't supported anywhere else)

* Reimplement unused variable warn + Discards

* Reimplemented discards in a simpler / hackier fashion by just having them be valid identifiers that are not actually declared at compile time.

* Reimplemented unused variable warnings.

* Reimplemented error when trying to use multiple parameters with same name

* Fix cases where variables aren't marked as used

* Fix "This" unused trace

Will make it point to the function itself.

* Fix fastest case condition with meta type

When this check is done the type and name haven't been inserted into param_types and param_names, so it was doing this despite being passed a method function

* Fix operators not marked as nonlegacy

Entity equality and bone equality were trying to run with legacy parameters

* Hopefully finally fix assignment parsing

* Fix parser's `Assert` error

Was using display from old code from before I made E2 take error structs instead of strings for error handling.

* Mark indexing assignment variables as used

* Rewrite vector operators

Now using registerOperator without legacy.

* Allow variable shadowing & Fix -> operator

* Variable shadowing is apparently supposed to be allowed in E2. So I changed the error to a warning.

* Fixed oversight when changing compiler `inputs` and `outputs` to the full IODirective struct (which broke the -> operator)

* Fix error compiling void recursion

* Simplify include code

Also implemented runtime scoping. Need to optimize it later though.

* Fix include scoping

* Fix some scopings

* Make foreach only push scope once for performance gains
* Add runtime scoping to switch case as it should have had.
* Use assert where verbose erroring was used to compact compiler code
* Store scope in for loop implementation as a micro-optimization rather than constantly indexing `state.Scope`

* Check for nil in switch

* Fix userfunction vararg check

* Disallow overriding variadic builtins with the variadic sugar as it currently is in the current compiler.
* Change the unit tests to account for this (better)

* Rewrite extpp

500 sLOC => ~350 sLOC.

Mostly rewrote external preprocessor so it now supports outputting functions that use the non-legacy form of creating functions now.

My eventual plan is to deprecate the preprocessor as a whole but it's nice that having this allows for extensions to be ported over to the new system automatically.

Additionally rewrote e2functions using the varargs to use ...<name> instead.

* Actually define the parameters

Got too used to using registerOperator which actually passes the arguments to the lua function directly rather than through a table as functions do.

I think it'd be possible to do that for functions but it'd require a lot of code duplication to be efficient. Maybe it could be looked into in the future.

* Fix extpp operator implementation

Last commit ironically broke operators since it does have the opposite implementation that passes arguments directly to the lua function.

* Fix changed() functions

Still a hacky function. Luckily works since we pass the type table which is compile time (and changed just needs an identifiable compile time index).

Made it cost 5 ops from 1 since you should not be using this function often if at all and I'd really love to remove it.

* Discard optimizations

* Fixed ioGetOutput
* Added optimized compile outputs with For and Foreach loops in case the key is a discard (_).

* Fully implement stringcalls

Still no caching

* Implemented string calls for builtin functions
* Implemented string calls for methods
* Fix string call parsing error

* Some fixes

* Fix event error that would normally prevent scoping events firing with includes (which the top level is scope 1, not the global scope).

* Fix one last use of incorrect 'variadic' variable

* Fix entity indexing returning nil when not found

* Add traces to quota and internal errors

Lua errors wouldn't point to an E2 trace or anything since they didn't have a trace attached to them. The trace is stored in the context however, which the entity has access to.

So now quota errors and internal lua errors by extension developers will point you toward whichever function caused it.

* Reimplement some warnings & Tidy code

* Reimplemented "use before initialization" warning.
* Rewrote nodiscard and deprecation warnings implementation to a less hacky method.
* Make nested event a warning as to not break backwards compat for a bit. Will make it an error in the future but I don't want to break more code.

* Removed progress comments. Redundant and haven't updated them in a while.

* Initialize variable on assignment

Forgot this

Also made the editor warning/error list traces more obvious as to being a trace. ([%d:%d] -> [line %u, char %u])

* Don't trigger non-table types

Assignment to global variables was trying to have the lookup behavior which was previously restricted to table-like types for I/O on any type, which was erroring in case of an entity.

* Missed a spot

There was another location where the previous commit's issue could be reproduced.

Also fixed an internal error on using deprecated methods.

* Fix wirelink indexget

* Fix preprocessor errors

* Fix sign and include variables

* Fix sign function which used its arguments incorrectly

* Fix incorrect runtime scoping of includes and removed Context:IsolatedScope

* Rework extpp some more

* Condensed to 300 lines (shaved off 70 lines)
* Make variadic parameters not use legacy functions.
* Revert change making printed strings quoted

* Remove E2Lib.Env.Types

These changes shouldn't be included in this PR. Will be done later with reworking the api.

* Remove support for single quat/complex literals

You can no longer have `i`, `j` and `k` act as valid expressions. This is because it was causing a parsing error for methods.

This is a breaking change but I really doubt anyone used this behavior, and it is silly. Additionally I've had a warning for using them since I rewrote the tokenizer, so if anyone was (and still actively keeps up with E2), they would know to change to 1k/1j/1i.

This would fix #2544

* Fix syntax error

This popped up when fixing merge conflicts

* Fixes & New tests

* Added a bunch more integration tests for E2, this time focusing on the runtime being correct.

* Fixed switch case fallthrough not existing (probably has been broken since my PR to fix the scoping issue and nobody's noticed)

* Fix issue with for loop break bleeding into other for loops, preventing them from running

* Fix the same thing above but switch case leaking into other things

* Fix parsing test case by removing use of quaternion/complex literal syntax that has been removed.

* Remove effect "assignment" operator.

* Fix event parameter checking being messed up with the event placeholder pr.

* Slightly optimize for loops more by using compile time known number of iterations (microoptimization)

There's still a bunch of E2s that behave very strangely. Investigating this is a huge pain

* Fix void return and add more function test cases

Thanks to h2n9 reporting this on discord

* Parity and a lot more tests

Added a lot more test cases.

Now foreach defaults to strings when iterating over tables as it did prior.

* Fixes & Cleanup

* `if` statement now properly uses `operator_is` as it was always meant to. It bypasses this for number and string, however, as an optimization.

* Fix issue with calls that contained nil values that broke `ipairs` by not using ipairs (potential speedup)

* Fixes, parity & test cases

* `types` param in extpp functions -> `typeids` as it was before
* Fixed if statement logic for when to skip using operator_is (and added test case)
* Add testcase for variadic extpp functions (testing printColor and print)
* Add test case to ensure array in array won't compile.

* Fixes & Parity

* Fix issue with method calls causing internal errors
* Fix assertion ensuring void isn't used as method type
* Add some left over operators to removedoperators
* Make increment and decrement use the existing addition and subtraction operators with the type to number. So now doing V++ is a thing (where V is a vec()).
* Fix variadic parameter syntax sugar issues and not including meta type in `types` table passed to functions.
* Add check to ensure if operator_is works on strings
* Added recursion and variadic syntax sugar tests.

* Fix vararg issues

* Fix variadic udf syntax sugar with a `table` including the meta type in the table's typeids.
* Clip `typeids` to only include the variadic variables in extpp. Was not aware this was expected behavior.
* Add some more variadic function tests (format and select)

* `types` -> `typeids`

I changed the parameter output in extpp thinking nobody was using it, bad idea.

Last extpp fixes reverted that, so need this to fix changed().

* Fix exit() and reset() not resetting scope

This wasn't a problem in the past, since statements would pcall their inner contents and pop their scopes before erroring. Now that we don't do that, since exit() and reset() just trigger an error, it caused the E2 to desync between runtime and compile time scope as it'd never pop its scope.

Now the functions reset the scope to the global scope before erroring.

This got the garfield pipe E2 working.

* Fix events not compiling, Remove some legacy support

* Removed support for legacy "is" operators inside of the "or" and "and" operator since people seem to be okay with some breakages. Also I wasn't supporting it anywhere else, so.

* Fix issue with events not compiling probably due to some failed merge when pulling in the changes with event parameter names.

* Revert "is" operators now using registerOperator

They now use the e2function syntax since it supports the new operators, and will be more forwards compatible.

* Proper multiline traces

* Fix incorrect stitching

Stitched to node which caused very weird internal errors

* Ordered table keyvalue creation

Uses numeric for loops rather than pairs which is faster and will have a defined order of which keyvalues will be assigned at table creation, unlike before.

Fixes #2494

* Fix delta ($) and deprecated wirelink index method

* Fixed delta's implementation. Seems I didn't even properly implement it. Added a test for it and made tests initialize variables with defaults like a normal chip would.

* Fixed old deprecated way of indexing a wirelink ie `WL:number("Foo")` instead of `WL["Foo", number]`. Can't really test this without IO, but added a basic sanity test.

Now drunk combine works.

* Fix old dupes with dupevars missed in #2462

Didn't think about delta vars at the time. Types aren't stored with them, so any $Vector or $Angle was not being converted, and would error old E2s with them duped.

So this fix is unrelated to my changes on the compiler..

Also reverted vector and angle operations to use e2function syntax once again, and made some vector functions use Vector metamethods rather than pure lua operations (Dot/Cross/Normalized/Distance/Length)

* Add variadic string call support & Legacy support

String calls now check for legacy functions at runtime. Also supports variadic calls except for user defined syntax sugar functions (Doubt people were relying on string calls with that new feature, and hopefully string calls will be deprecated soon).

Added stringcall tests to enforce return type errors, ensure functions work through stringcalls.

* Cleaner E2Lib.compileScript

Use withStrict instead of manually defining throw function.

Add with(Inputs/Outputs/Persists/DeltaVars) methods to handle initializing variables to default values rather than doing it manually.

* Remove unused `run` param

* Slight tweaks

* Store scope before loop in foreach implementation to avoid indexing op each iteration
* Made variables and costless functions cost cheaper.

* Fix parser trace error

Seems I missed this one

* Remove assignment operator

* Fix assignment not reusing expression

Seems I got sidetracked while implementing this, and didn't properly make it re-use the final expression in assignment. This lead to simply doing `A = 2` evaluating the '2' expression twice, which is a big problem for function calls.

Added a regression test as well.

* String library fixes

* Make format use ...args syntax instead of ...
* Remove operator!=
* Make use of string.byte's index parameter rather than doing string.sub to get the character in byte foreach

* Add stringcall array restriction edge case

* Fix removed operators not preprocessing

Now it just generates a pointless lambda as to not cause syntax errors.

Additionally moved the check to the bottom of the error list since it's a warning rather than an error.

* Enforce new void representation

Void type is represented as just nil now instead of an empty string.

To enforce this, check for empty string inside of compiling exprcall.

Ideally the api just wouldn't pass an empty string now but stuff like e2doc depends on that afaik. Just easier to go about it this way for now.

* Variadic user function stringcall support

* Add stringcall method function test

* Rearrange tests & Add library tests

Now the runtime test suite is split into three parts

* Base: Testing that compiler things like if statements, while loops, etc work
* Libraries: Testing that libraries like `string` work as they are changed.
* Types: Testing that types function properly

* Temporary overriding return patch

Also added test. This code shouldn't have been uncommented, just need to handle that one case where fn.returns is expected to not be nil.

* Fix operator= causing errors

Add to RemovedOperators list and check RemovedOperators list before flagging something as an invalid function name

* Proper function override fix

* Fix incorrect error message on event error

Bad copy paste job gave a tick quota error inside of runtime errors in events

* Fix for loop continue bleeding

Also added test case to ensure this doesn't happen again. (And to explain the issue for me)

* Fix foreach not having break return and continue implemented

No idea how this didn't have any tests and wasn't found.

Also simplified for loop code

* Fix user function overriding, add override optimization

Fix user function overriding by properly looking up the function at runtime.

This would normally incur runtime overhead for all functions, but now the compiler tags functions to be `const` if they are never re-declared anywhere else. This means we can get the best of both worlds with performance with or without function overrides.

As per usual, added tests

* Fix switch case early break

Also added a bunch more test cases

* Fix nil argument stopping udf arguments

Was using ipairs internally, which would fail on a table with a gap caused by a nil argument.

* Reimplement runtime undefined function error

* Fix keyvalue calls not accepting identifiers

This is an issue that's existed for 10+ years on the old compiler but nobody has found it since it's pretty niche to even use the key value table/array constructor functionality.

Hacky fix but couldn't think of any other way. This is the fault of two things: E2 not having braces like lua does for expressions in these kv constructors, and E2 using the assignment operator inside them as well. So not much we can do about it besides this.

Added test to ensure it works correctly.

* Fix dupes

Wasn't converting the typeid back to non-type id form for the duplicator

* Fix while loop continue

While loops weren't being tagged as loop (which evaluating blocks uses to determine whether to look for continue/break/etc or not)

While also had the continue scope bleeding issue that for/foreach had patched a bit ago.

* Add stackdepth to runtimecontext builder

* notify for syntax errors again

* Fix switch fallthrough running same case twice

Fixes Vurv78#12

* Add default == operator in case it is absent

One goal of this PR is to minimize the amount of third party code needed in E2 extensions.

Now the equals operator can be omitted if the implementation intends to be a simple lua equals operation.

This not only saves on needing to implement a redundant function, relying on extension authors to maintain this, but leaves room for optimizations knowing that the operator is "simple", like compiling switch case to a lookup table of lambdas, which wouldn't be possible if the equals operator was overloaded since it'd use table indexing with the value.

Additionally added more test cases.

This behavior may also come to operator_is in the future. For now, since overloading it with valid nonsimple functions is common, it will stay necessary.

* Don't store scope in VarData

Was only using the scope field for the depth. Storing it in VarData lead to cyclic reference which couldn't be serialized in JSON, breaking dupes.

* Rewrite compound operator, decrement/increment operators

This fixes the case of compound operators alongside increment/decrement not working with types that had legacy operators.

Now these will simply act as syntax sugar for assignment and use the operators internally, now that I've removed the compound assignment operators.

It simplifies the compiler implementation of these significantly and deduplicates a lot of code regarding variable usage

* Remove redundant "is" return enforcement

Enforce that no operator is registered named "is" that returns a type other than "n", and remove redundant runtime enforcement of this in Not operator compilation

* ExtPP tweaks

Trim string before gsub, and remove extra argument passed to parseParameters

* Highlight and autocomplete user defined functions

* Fix string and byte foreach, add tests

They were cutting off one char/byte early

* Add explicit catch error typing

Adds explicit error typing to the error variable in try catch, with a warning if not present.

Added highlighting and test case for this.

* Change nontable foreach warning message

* Fix ExtPP generating trailing whitespace for aliases

Fixes #2667

* Split parsing test into several files

* Deprecate E2Lib.raiseException

Deprecate E2Lib.raiseException in favor of new function, RuntimeContext:forceThrow.

Now only in the case of non-strict, a runtime context's throw function is overridden with one that returns the default value, otherwise it inherits the function from its metatable.

forceThrow uses this inherited function.

Added coverage for early returns to unit test suite, change __return__ check position

Removed old string function implementation (completely scrapped for raw compiler implementation)

* Fix precedence of certain operators

Optimizing the parser led me to accidentally mess up the precedence of certain operators.

Specifically | should've had less precedence than &, but this was not true, they had the same precedence.

Added test cases for these operators.

Also optimized delta operator since the scope will always be the global scope.

* Remove preprocessor attribution

Incorrect and I'd rather not be connected to that

* Optimize runtime scoping

Remove SaveScopes and LoadScopes functions, inline their contents to avoid allocation of a redundant table and the function overhead.

* Fix preprocessor error causing internal error

---------

Co-authored-by: Fasteroid <29342750+Fasteroid@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants