OpenHSP icon indicating copy to clipboard operation
OpenHSP copied to clipboard

Question about how modules function

Open jdstroy opened this issue 10 months ago • 2 comments

Hi Onitama,

I hope this is the right place for this question; if it is not, I apologize.

I have successfully created a library/module in HSP implementing a dynamically-sized array (e.g. similar to vector in C++ or ArrayList<T> in Java).

I am trying to make the module more useful and reusable by implementing functionality such as binary search, but for the module/library to be more useful, it would be good to have user callbacks within the library/module code (for example, a comparison function provided by the caller of the dynamic array module).

I tried making the callback a module, too, but it appears that symbol resolution happens at compilation, and not at runtime dispatch, so this code can only work with one implementation of the compare function, regardless of what module is passed as comparator to bSearch@VArrayListSSCCE:

#module math
	#defcfunc min int x, int y
	    if (x < y) {
		    return x
		}
	return y
	
	#defcfunc max int x, int y
	    if (x > y) {
		    return x
		}
	return y
	
	#defcfunc sign int k
		if (k > 0) {
			return 1
		}
		if (k < 0) {
			return -1
		}
	return 0
#global

#module VArrayListSSCCE contents, _size, capacity	
	#modinit int maxSize
		_size = 6
		capacity = 10
		dim contents, capacity
		contents.0 = -20
		contents.1 = 81
		contents.2 = 82
		contents.3 = 83
		contents.4 = 84
		contents.5 = 184
	return
	
	#modcfunc size
	return _size
	
	#modfunc get int index, var output
		assert (index >= 0)
		assert (index < size(thismod))
		output = contents(index)
	return
	
	#modcfunc toString local output, local idx, local value
		output = strf("{ 'size': %d, 'capacity': %d, 'contents' : [", size(thismod), capacity )
		for idx, 0, size(thismod), 1
			get thismod, idx, value
			output = strf("%s %s,", output, value )
		next
	return strf("%s ]}", output)
	
	#modcfunc bSearch var value, var comparator, local lowIdx, local midIdx, local hiIdx, local tmpVal
		lowIdx = 0
		hiIdx = size(thismod)
		while 1
			midIdx = (hiIdx + lowIdx) / 2
			get thismod, midIdx, tmpVal
			switch (sign(compare(comparator,tmpVal,value)))
				case 0:
					return midIdx
				swbreak
				case 1:
					if (lowIdx == midIdx) {
						return -1
					}
					lowIdx = midIdx
				swbreak
				case -1:
					if (hiIdx == midIdx){
						return -1
					}
					hiIdx = midIdx
				swbreak
			swend
		wend
	return
#global

#module SubtractionComp notused
	#modinit
		notused = 0
	return
	#modcfunc compare var x, var y
	return sign(y - x)
#global	

newmod comparator, SubtractionComp

newmod demo, VArrayListSSCCE, 0
mes toString(demo)

m = 84
mes strf("bSearch(list, %d, comparator) = 4: %s", m, bSearch(demo, m, comparator))

m = 81
mes strf("bSearch(list, %d, comparator) = 1: %s", m, bSearch(demo, m, comparator))

m = 75
mes strf("bSearch(list, %d, comparator) = -1: %s", m, bSearch(demo, m, comparator))

That is to say, in the above example, compare is resolved to compare@SubtractionComp; and I can completely remove SubtractionComp from a project, and replace it with this:

#module BadComp notused
	#modinit
		notused = 0
	return
	#modcfunc compare var x, var y
	return x ^ y
#global

newmod comparator, BadComp

But both cannot exist in the same project at the same time. Is there a way for someone using this module to provide such a callback function for bSearch@VArrayListSSCCE?

Many thanks in advance.

jdstroy avatar Jun 10 '25 03:06 jdstroy

One possible solution is to use label variables as function pointers and global variables as function arguments and return values.

https://www.onionsoft.net/hsp/v34/doclib/hspprog.htm#LABEL

zakki avatar Jun 10 '25 04:06 zakki

Hello zakki, thanks for the suggestion!

Is there a way to use label variables to point to functions (#defcfunc/#modcfunc) or subroutines (#deffunc/#modfunc)?

jdstroy avatar Jun 13 '25 02:06 jdstroy