Select Case
 

Basic реализация

dim i as integer		dim i as integer

				scope
select case i + 123			dim temp as integer = any
					temp = i + 123

case 1					if( temp <> 1 ) then goto cmplabel1
					scope
	print "1"				print "1"
					end scope
					goto endlabel

case 2					cmplabel1:
					if( temp <> 2 ) then goto cmplabel2
					scope
	print "2"				print "2"
					end scope
					goto endlabel

case else				cmplabel2:
					scope
	print "else"				print "else"
					end scope

end select				cmplabel3:    '' не используется только потому, что в этом примере последний CASE не обусловлен
					endlabel:
				end scope

  • SELECT CASE
    • открывает неявную внешнюю область видимости
    • объявляет временную переменную
      • когда внутри процедуры STATIC, временная переменная будет STATIC
      • FB_SYMBATTRIB_TEMP удален из временной переменной, потому что он живет дольше, чем всего один оператор
    • выдает назначение
    • объявляет о завершении метки
  • каждый CASE
    • если была предыдущая CASE
      • закрывает предыдущую область видимости CASE
      • издает переход в конец метки
    • издает метку для этого CASE
    • Выдает условный переход, который переходит к следующему CASE, если условие CASE не соблюдается
    • Открывает область видимости CASE
    • CASE ELSE не выделяет условный переход
    • Как только CASE ELSE был использован, никакие дальнейшие блоки CASE не допускаются
  • END SELECT
    • закрывает предыдущую область видимости CASE
    • выпускает дополнительную метку CASE в конце (Нет никакого CASE больше, но это позволяет последнему CASE переходить до конца, если это - условный CASE. Последний CASE мог перейти к метке конца SELECT вместо этого, но это потребует некоторого кода обработки особого случая.)
    • выдает конечную метку
  • Любой EXIT SELECT прыгает сразу до конечной метки


SELECT CASE на strings/zstrings/fixstrs

dim s as string			dim s as string

				scope
select case s + "1"			dim temp as string

					fb_StrAssign( temp, s )
					fb_StrConcatAssign( temp, "1" )

case "1"				if( fb_StrCompare( temp, "1" ) <> 0 ) then goto cmplabel1
					scope
	print "1"				print "1"
					end scope
					goto endlabel

					cmplabel1:
end select				endlabel:
					fb_StrDelete( temp )    '' удаляет временную переменную в конце области видимости
				end scope

				fb_StrDelete( s )

  • SELECT CASE на string/zstring/fixstr выражениях использует строковую временную переменную
    • вероятно, потому что это просто
    • зная длину строки потенциально ускоряются следующие сравнения
    • динамическое распределение памяти может быть слишком медленным вниз
  • строковая временная переменная уничтожается в конце области видимости или при преждевременном выходе из нее (например, достигая END SELECT, или EXIT FUNCTION в блоке CASE)

SELECT CASE на wstrings

dim w as wstring * 10			dim w as wstring * 10

					scope
select case w + wstr( "1" )			dim temp as wstring ptr

						dim tempexpr as wstring ptr = w + wstr( "1" )
						temp = fb_WstrAlloc( fb_WstrLen( tempexpr ) )
						fb_WstrAssign( temp, tempexpr )

case wstr( "1" )				if( fb_WstrCompare( temp, wstr( "1" ) ) <> 0 ) then goto cmplabel1
						scope
	print "1"					print "1"
						end scope
						goto endlabel

						cmplabel1:
end select					endlabel:
						fb_WstrDelete( temp )    '' удаляет временную переменную в конце области видимости
					end scope

  • подобно SELECT CASE на zstrings, для wstring выражений wstring динамично выделяется
  • временный wstring рассматривается во многом так же , как динамический объект wstring
    • это VAR символ  с типом WCHAR PTR
    • отмечается с FB_SYMBSTATS_WSTRING
    • это позволяет проверкам ctor/dtor распознавать его и правильно обрабатывать
  • таким образом, временный wstring разрушается в конце области видимости или преждевременном выходе из нее


SELECT CASE без временной переменной

Это тогда , когда переменная будет вместо более сложного выражения, SELECT CASE не будет использовать временную переменную, но вместо этого отложит символ из данного выражения и доступ, в случае сравнения выражений.???