ID:1929429
 
BYOND Version:508
Operating System:Windows 7 Ultimate 64-bit
Web Browser:Chrome 44.0.2403.157
Applies to:DM Language
Status: Open

Issue hasn't been assigned a status value.
Descriptive Problem Summary:
In the code below, text2path("/DerivedObject/Use") returns null.
This is a problem for using call()() dynamically.
Furthermore, ispath(/DerivedObject/Use) and ispath(/DerivedObject/proc/Use) don't work either.

Numbered Steps to Reproduce Problem:
1. Derive DerivedObject from BaseObject
2. Make and try to get the path of an overwritten inherited proc using text2path()

Code Snippet (if applicable) to Reproduce Problem:
//Create these.
BaseObject
proc/Use()
world << "Whatever is in here doesn't matter."
DerivedObject
parent_type = /BaseObject
Use()
world << "Whatever is in here doesn't matter either."

//Run this.
world << text2path("/DerivedObject/Use") // Blank/null
world << ispath(/DerivedObject/Use) // 0
world << text2path("/DerivedObject/proc/Use") // Blank/null
world << ispath(/DerivedObject/proc/Use) // Compiler error.


Expected Results:
text2path("/DerivedObject/Use") to work and return the correct path, as it does for text2path("/BaseObject/proc/Use"). Not sure of the behavior of ispath(/DerivedObject/Use).

Actual Results:
We get null and 0 respectively.

The problem occurs:
Every time.
In other games.
In other user accounts.
On other computers.

When does the problem NOT occur?
Never.

Did the problem NOT occur in any earlier versions? If so, what was the last version that worked?
Not tested.

Workarounds:
Don't inherit the proc.
I will note that the behaviour of ispath() when applied to procs is currently AFAIK the only way to tell a proc path from a non-proc path; it'd be nice if, if that's changed so that ispath(/proc/thing) == 1, we could get some kind of isprocpath() proc.
Yeah, I don't really care about ispath() returning 0 or 1 for procs, I care about text2path not returning null for overwritten procs, since my calls require it.
I'm not sure what you are trying to do with this.

Why not use hascall() to check if a proc exists?
Using call()() to call the base proc will call the overridden proc fine, if that's your worry.

Additionally, you can use just the name of the proc to call it, you don't need to text2path it (hascall() example included):
/datum/proc/example()
return 1

/client/verb/test()
var/datum/D = new
var/procname = "example"
if(hascall(D, procname))
world << call(D, procname)() // prints "1"
I'm not trying to check if a proc exists, and the method GinjaNinja32 described does not work due to the proc not actually existing in the call Object's path, if there is even a call Object at all, but rather another path, for reasons such as organization and inheritance benefits. They are handlers for skills. I need the path in order to call a proc globally and dynamically at runtime. I'd rather not instantiate the "static" class and waste resources on creating an object if I can avoid it.
The bug here is that text2path() doesn't work on inherited procs.
parent
proc/Proc() world << "parent proc"
child/Proc() world << "child proc"

mob/Login()
// this works:
call(/parent/proc/Proc)()
call(/parent/child/Proc)()

src << text2path("/parent/proc/Proc")

// this doesn't (blank output):
src << text2path("/parent/child/Proc")

ispath() seems to return false on all proc paths, but that might be intended since proc paths aren't type paths.
Yup, Kaiochao got it right. I didn't fully test the functionality for ispath(), I just put it there because I thought it may be helpful to solve the text2path() problem. In any case, I don't need ispath() to return anything at all, just text2path().
I'm not trying to check if a proc exists, and the method GinjaNinja32 described does not work due to the proc not actually existing in the call Object's path, if there is even a call Object at all, but rather another path, for reasons such as organization and inheritance benefits. They are handlers for skills. I need the path in order to call a proc globally and dynamically at runtime. I'd rather not instantiate the "static" class and waste resources on creating an object if I can avoid it.

This is the most nebulous explanation I've ever read. I actually understand what you are talking about even less than before you explained what you are doing.

I get that you are trying to emulate the static pattern to avoid intializing objects, but I really doubt that initializing the object once is going to have less overhead than a text2path and an indirect call every time you want to call the proc.
Perhaps you're right, but it's still a bug, and that's only a workaround. And I only need to use text2path() once, just like initializing the object once. So it's more or less the same. Just a matter of clean and consistent code, and personal preference. I will use that method if this bug won't get fixed, I guess.
So it's more or less the same.

IIRC, indirect calls have to do a tree look-down as well as an invocation look-up, whereas proc invocation only needs to do an invocation look-up.

This is only a bug in that it's a half-implemented feature that never should have worked in the first place. Using prototypes as a sort of awkward namespace is very concerning. It seems to me like you are trying to use a pattern that just doesn't make sense in the context of DM.

I think you are screwing yourself in the long-run by depending on this syntactic quirk, because it's going to be more resource intensive. If you are worried about object counts or memory, don't be. You'll hit the CPU bottleneck long before either of those become a problem.
Okay. I wish more of this inner-workings stuff was available to the public, so I can know what is the more optimized approach. It's true that I'm trying to make DM work more like C#, for consistency's sake (I develop a lot in C/C++/C#). I'll probably use the workaround though, but either way, this bug should be fixed in that either overwritten procs work or procs shouldn't work at all with text2path(), so people won't get confused.
EDIT: Okay, I applied the workaround, wasn't too hard with the code I already have. It's pretty extendable. Still, don't disregard my previous statement for too long. Just to keep the language consistent.
Odds are this is a remnant of some incomplete Dan code from 1999 or 2000.
Probably. In that case, maybe it's not worth the trouble to keep it consistent...
text2path() looks up the string in the string tree, and then looks to see if any type paths's are pointing to that same exact string.

It does very little (if any) fuzzy checking.

I think you would need to do:

/BaseObject/DerivedObject/Use and that's assuming it doesn't require you fully complete it: /datum/BaseObject/DerivedObject/Use

And it would only work if that object had that proc overridden.
I think I tried that, but I'm not sure. The path that BYOND spits out is indeed /DerivedObject/Use though. I might test that separately since I already changed how I call procs dynamically.
The bug here is that text2path() doesn't work on inherited procs.

Maybe it's a good moment with some changes in 515 with nameof()/call(), so I want to bump this.

Is there a way to dynamically get proc reference of child object proc? Or would it be hard to fix text2path() for this?

I know, it's some weird programming, and I can work around it. It's not important.
Child procs don't have their own type paths. Thus there's no way to "fix" text2path(); it isn't actually broken.

From within a proc, you can get a reference to the proc itself in 515 with the new __PROC__ pseudomacro.