[Solved] Instantiation attempted on a non-constructor

I am trying to develop a code editor that - where you are able to develop using OpenFL classes and enums - will accept all the classes and enums as required to develop a game at runtime using the HScript library. I’ve got this far, but it seems that when I parse the code at runtime it does not seem to detect the classes/enums:

_classKeywords = ClassPaths.split(";");
for (fullPath in _classKeywords)
            {
                var shortName = fullPath;
                if (fullPath.indexOf(".") > -1) {
                    shortName = fullPath.substring(fullPath.lastIndexOf(".") + 1, fullPath.length);
                    _classHighlighters.push(shortName);
                }
                _interp.variables.set(shortName, Type.resolveClass(fullPath));
            }
            
            _enumKeywords = EnumPaths.split(";");
            for (fullPath in _enumKeywords)
            {
                var shortName = fullPath;
                if (fullPath.indexOf(".") > -1) {
                    shortName = fullPath.substring(fullPath.lastIndexOf(".") + 1, fullPath.length);
                    _enumHighlighters.push(shortName);
                }
                _interp.variables.set(shortName, Type.resolveEnum(fullPath));
            }

For some reason, when I parse the code from the interpreter, I get the error:

TypeError: Error #1007: Instantiation attempted on a non-constructor.
    at Type$/createInstance()
    at hscript::Interp/cnew()
    at hscript::Interp/expr()
    at hscript::Interp/expr()
    at hscript::Interp/exprReturn()
    at hscript::Interp/execute()
    at CodeEditor/parseCode()
    at CodeEditor/keyUp()

From what I can tell from looking around a bit, it seems Flash is just “I can’t find this class, so I can’t create it.” What is the best way to go around it, and is the Type.resolveClass() a function that should be used to pass in a Class to the interpreter?

If you trace fullPath and Type.resolveClass(fullPath) does it look correct?

Does it work in target other than flash, like neko or native (windows/mac/linux)?

I have done a trace on fullPath and shortName, both output as expected.

i.e. openfl.display.Sprite is the full path, and shortName is Sprite.

The resolveClass function just returns null when passing in either the shortName or the full path, so I am unsure what is going on there. I have not tested it on native targets, but I expect a crash should it fail.

If it helps, the string I pass into the ClassPaths to be split and read looks like this:

openfl.display.Sprite;openfl.text.TextField;openfl.Assets;openfl.Lib;openfl.Memory;openfl.display.TextureUvs;openfl.display.BitmapDataChannel;openfl.display.Graphics;openfl.display.GraphicsPathCommand;openfl.display.JPEGEncoderOptions;openfl.display.PNGEncoderOptions;openfl.display.Tilesheet;openfl.display3D.SamplerState;openfl.display3D._shaders.AGLSLShaderUtils;openfl.errors.Error;openfl.events.Event;openfl.events.Listener;openfl.external.ExternalInterface;openfl.filters.BitmapFilter;openfl.filters.BitmapFilterQuality;openfl.filters.BitmapFilterType;openfl.geom.ColorTransform;openfl.geom.Matrix;openfl.geom.PerspectiveProjection;openfl.geom.Point;openfl.geom.Rectangle;openfl.geom.Transform;openfl.media.SoundJS;openfl.media.SoundJSEventDispatcher;openfl.media.SoundLoaderContext;openfl.media.SoundTransform;openfl.net.URLRequest;openfl.net.URLRequestHeader;openfl.net.URLRequestMethod;openfl.system.ApplicationDomain;openfl.system.Capabilities;openfl.system.LoaderContext;openfl.system.Security;openfl.system.SecurityDomain;openfl.system.System;openfl.text.Font;openfl.text.TextFormatRange;openfl.text.TextFormat;openfl.text.TextLineMetrics;openfl.ui.Keyboard;openfl.ui.Mouse;openfl.ui.Multitouch;openfl.utils.AGALMiniAssembler;openfl.utils.Endian;openfl._internal.aglsl.AGALTokenizer;openfl._internal.aglsl.AGLSLCompiler;openfl._internal.aglsl.AGLSLParser;openfl._internal.aglsl.Description;openfl._internal.aglsl.Destination;openfl._internal.aglsl.Header;openfl._internal.aglsl.Mapping;openfl._internal.aglsl.OpLUT;openfl._internal.aglsl.Sampler;openfl._internal.aglsl.Token;openfl._internal.aglsl.assembler.Flags;openfl._internal.aglsl.assembler.FS;openfl._internal.aglsl.assembler.Opcode;openfl._internal.aglsl.assembler.OpcodeMap;openfl._internal.aglsl.assembler.Part;openfl._internal.aglsl.assembler.Reg;openfl._internal.aglsl.assembler.RegMap;openfl._internal.aglsl.assembler.Sampler;openfl._internal.aglsl.assembler.SamplerMap;openfl._internal.renderer.AbstractRenderer;openfl._internal.renderer.RenderSession;openfl._internal.renderer.canvas.CanvasBitmap;openfl._internal.renderer.canvas.CanvasGraphics;openfl._internal.renderer.canvas.CanvasShape;openfl._internal.renderer.canvas.CanvasTextField;openfl._internal.renderer.canvas.MaskManager;openfl._internal.renderer.dom.DOMBitmap;openfl._internal.renderer.dom.DOMShape;openfl._internal.renderer.dom.DOMTextField;openfl._internal.renderer.opengl.GLBitmap;openfl._internal.renderer.opengl.GLTextField;openfl._internal.renderer.opengl.shaders.AbstractShader;openfl._internal.renderer.opengl.utils.BlendModeManager;openfl._internal.renderer.opengl.utils.DrawPath;openfl._internal.renderer.opengl.utils.PathBuiler;openfl._internal.renderer.opengl.utils.LineStyle;openfl._internal.renderer.opengl.utils.FilterManager;openfl._internal.renderer.opengl.utils.FilterTexture;openfl._internal.renderer.opengl.utils.GraphicsRenderer;openfl._internal.renderer.opengl.utils.GLStack;openfl._internal.renderer.opengl.utils.GLBucket;openfl._internal.renderer.opengl.utils.GLBucketData;openfl._internal.renderer.opengl.utils.GLGraphicsData;openfl._internal.renderer.opengl.utils.PolyK;openfl._internal.renderer.opengl.utils.MaskManager;openfl._internal.renderer.opengl.utils.ShaderManager;openfl._internal.renderer.opengl.utils.SpriteBatch;openfl._internal.renderer.opengl.utils.State;openfl._internal.renderer.opengl.utils.StencilManager;openfl._v2.Assets;openfl._v2.AssetLibrary;openfl._v2.AssetData;openfl._v2.Lib;openfl._v2.Memory;openfl._v2.display.OptimizedPerlin;openfl._v2.display.Graphics;openfl._v2.display.IGraphicsData;openfl._v2.display.TouchInfo;openfl._v2.display.Tilesheet;openfl._v2.events.Event;openfl._v2.events.Listener;openfl._v2.external.ExternalInterface;openfl._v2.feedback.Haptic;openfl._v2.filesystem.File;openfl._v2.filesystem.StorageVolume;openfl._v2.filters.BitmapFilter;openfl._v2.geom.ColorTransform;openfl._v2.geom.Point;openfl._v2.geom.Rectangle;openfl._v2.geom.Transform;openfl._v2.gl.GL;openfl._v2.gl.GLObject;openfl._v2.media.AudioThreadState;openfl._v2.net.URLRequest;openfl._v2.net.URLRequestMethod;openfl._v2.system.Capabilities;openfl._v2.system.ScreenMode;openfl._v2.system.System;openfl._v2.text.AbstractFont;openfl._v2.text.Font;openfl._v2.text.TextFormat;openfl._v2.text.TextFormatAlign;openfl._v2.text.TextLineMetrics;openfl._v2.ui.Accelerometer;openfl._v2.ui.Keyboard;openfl._v2.ui.Mouse;openfl._v2.ui.Multitouch;openfl._v2.utils.JNI;openfl._v2.utils.JNIMemberField;openfl._v2.utils.JNIStaticField;openfl._v2.utils.JNIMethod;openfl._v2.utils.SystemPath;

No, I did not do all that manually :wink: I created a small program that reads all the .hx files in the base directory of the source code of a library, and converts the directory path to its respective full path in code.

Looking at the first openfl.display.Sprite,
in openfl’s code it’s a typedef: typedef Sprite = flash.display.Sprite;
I wonder if that changes anything once at runtime.

Does it work if you try to load a “normal” class you made yourself?

What if you do a replace from “openfl.” to “flash.”?
Though not all classes are flash classes or vanilla copy.

Ah yes, I didn’t think about that. If you pass in the TextField class just as it is into the interpreter, I’d expect at runtime it would be considered “flash.text.TextField”, not OpenFL.

However, native is the target I am looking to distribute this editor in anyway, Flash is merely for testing.

When I did export using the windows target, I did get some errors:

openfl.text.TextField has no field tabEnabled
openfl.text.TextField has no field caretIndex

It will probably help if I upgrade from 2.2.8 to 3.0.x but I don’t know what the situation is with the Beta yet, and I am hoping the TextField is more supported now on native than it used to be. I will try neko as well.

The aim, however, is to implement the ability to load libraries at runtime as well, which is why I am using this approach. By converting the paths and directories to their appropriate class types at runtime when you pass in the library path.

EDIT: Although, now that I have just tested the neko target it’s also complaining about the field’s not existing.

HScript provides access to all classes by default. It’s actually a pretty big security hole.

Try disabling all those variables and then inputting this:

flash.Lib.current.visible = false;

Why am I clearing all of the children?

It is odd, however, that it the cnew() function in HScript attempts to resolve a class anyway, but that is ironic since when I comment out the code as seen in the OP, the HScript interp complains the variable “TextField” does not exist when using the following script code:

var myText = new TextField();
myText.x = 50;
myText.y = 50;
myText.text = "Hello";

Lib.current.stage.addChild(myText);

I’ve written my own errors as follows:

try 
        {
            var parsed = _parser.parseString(_mainText.text);
            _interp.execute(parsed);
            trace("Successfully parsed.");
        }
        catch (err:Error)
        {
            var erObj:ErrorObject = new ErrorObject();
            erObj.LineNumber = _parser.line;
            erObj.CharNumberTo = err.pmax;
            erObj.CharNumberFrom = err.pmin;
            switch (err.e)
            {
                case ErrorDef.EUnterminatedString: erObj.ErrorText = "String was not terminated with a single- or double-quote as expected.";
                case ErrorDef.EUnknownVariable: erObj.ErrorText = "The variable could not be found. Have you misspelt or forgot to declare it?";
                case ErrorDef.EInvalidIterator: erObj.ErrorText = "Cannot iterate over this variable. Is this variable an array?";
                case ErrorDef.EInvalidOp: erObj.ErrorText = "The operator given cannot be applied to this type.";
                case ErrorDef.EInvalidAccess: erObj.ErrorText = "Cannot access variable, member or class. Are you missing an include?";
                case ErrorDef.EUnterminatedComment: erObj.ErrorText = "The given comment does not terminate. Are you missing an close block?";
                case ErrorDef.EUnexpected: erObj.ErrorText = "The given expression cannot be evaluated.";
                case ErrorDef.EInvalidChar: erObj.ErrorText = "The character given is not valid for this expression.";
            }
            trace("Errors found.");
            trace("" + erObj.LineNumber + "(" + erObj.CharNumberFrom + " - " + erObj.CharNumberTo + "): " + erObj.ErrorText);
            
        }

When parsing the former code, I get “The variable could not be found.” pointing to line 1, characters 13-27, that being the TextField “variable” that it’s trying to parse.

Anyway, I’m having another problem now because after upgrading to OpenFL 3.0.3, the windows target does not seem to allow me to place input on the TextField which I am confused about…

I’ve got my project on Github if you wish to help.

Everything is a child of Lib.current unless you explicitly add it to the stage. So when you make Lib.current invisible, you make everything else invisible too.

You’d need to write import flash.display.TextField; first, unless you wanted to type out new flash.display.TextField().

Nevermind. I got it working in the end:

#if flash
editor.ClassPaths += "flash.display.Sprite;flash.text.TextField;flash.Lib;flash.Memory;flash.display.TextureUvs;flash.display.BitmapDataChannel";

It resolves the class as expected, and clearing the children is impractical as you will find in the below screenshot:

Now I just need the TextField to work in native targets, but I suppose I can wait while I’m developing the core features of this application for now…

Not really.

var stage = flash.Lib.current.stage;
for(i in 0...stage.numChildren) {
    stage.removeChildAt(0);
}

I guess a code editor isn’t a security-critical application, but it would be confusing to write a game that showed up in the same window you were programming in.

Why not use the actual Haxe compiler?

Well, the aim of the program is to be able to make a game without needing to compile; being able to test game code on the fly without compilation, the ability to drag-and-drop TextField’s, Sprites, Sounds etc. into the Stage and auto-generating the expected code, in addition to property dialogs, event handling. And while testing, you would be able to track variables as you play, set breakpoints and modify the code as you test and play at the same time. The ultimate aim is to speed up video game development A LOT!

You barely would ever need to compile except on the occasion that you release your game or patch it to the public.

Hmm…

I guess, but HScript is pretty slow. Eventually it’ll be faster to compile it normally, considering how quickly Haxe compiles to Flash.

This has been tried before, with mixed results.

That might be too much. It’s starting to sound like you’re making a UI library in addition to the editor.

Actually, this might work well as its own library. Include the library in an existing project to place a console onscreen, and then view/edit values from within the console.

HScript can do this? Huh.

From my experience, with my project StoryDev HScript does not seem to be that slow.

I was thinking of implementing breakpoints in the sense that when the parser reaches a specific line, the rest of the code is split up into an array of strings. Stepping into/over would execute the next string in the array and being able to track all the variables that changed since the previous execution. That would require a lot of thought, ofc, since it would mean knowing what to do when a new function arrives, knowing which line that is, what to do when you hit a for/while loop etc. It would get insanely complicated but certainly a challenge I would love to experiment with.

I’m going to create a discussion about this because this is going way off-topic now.