Proposal: [126] Input values other than true and false

Accepted

This proposal has been moved into this section. Its former address was: /standard/tools/BracketIF

This page is dedicated to discussing this specific proposal

ContributeContributions

AntonErtlavatar of AntonErtl [126] Input values other than true and falseProposal2020-01-11 12:07:07

Problem

"flag" is speficied as:

Flags may have one of two logical states, true or false.

So what happens if you give a value other than true or false to [if]? Looking at the specification, that would be a non-standard program, but without stating that explicitly (and it's probably unintentional).

Existing Practice

Testing a number of Forth systems with the following code:

1 [IF] .( true ) [ELSE] .( false ) [THEN]

Gforth, SwiftForth, VFX, iForth, PFE and lxf output "true", so there is common practice for accepting all non-zero values as true (like IF); (spf apparently does not support [IF]).

Proposal

Replace

( flag | flag "<spaces>name ..." -- )

If flag is true, do nothing.

With

( x | x "<spaces>name ..." -- )

If any bit of x is set, do nothing.

KrishnaMyneniavatar of KrishnaMyneni

I feel this is a step backwards. I think the stack diagram should remain and [IF] should throw an error for an argument which is not Boolean (TRUE or FALSE).

alextangentavatar of alextangent

Why?

You give no reason for doing something that is anathema to (most sane) standards; that is, tightening a definition in a direction that no implementation supports, and that would have a large & unknown effect on extant code.

gnuarmavatar of gnuarm

Given that [IF] accepts only flags as the input type, the only word in the forth standard that specifies this. If that is the appropriate action for [IF], then should that also apply to IF, WHILE, UNTIL, etc.???

I'm sure it would break a great deal of code to tighten up the definition of IF to only accept flags as input. The standard specifically talks about this.

A.3.1.3.1 Flags A FALSE flag is a single-cell datum with all bits unset, and a TRUE flag is a single-cell datum with all bits set. While Forth words which test flags accept any non-null bit pattern as true, there exists the concept of the well-formed flag.

While it goes on to talk about issues with certain logic words and flags, it has clearly set the intent for valid inputs to conditionals including all numbers and not just flags. This concept goes all the way back to "Starting Forth" and is embodied in every system I've used. Why should [IF] be defined differently from IF in terms of the inputs???

KrishnaMyneniavatar of KrishnaMyneni

@alextangent I don't doubt the proposer's statement that the standard's description of [IF] was probably unintended, and that my suggestion has little chance of being adopted; however, it is worth considering for the following reasons:

  1. Keeping the requirement of a well-formed flag for [IF] will ensure that programmers provide greater precision in the logical operand to [IF].

  2. Your claim that it will have an unknown effect on extant code is incorrect. Existing source code which does not provide a well-formed flag to [IF] will simply fail to load. This gives the authors a chance to fix the problem. For example, "1 [IF]" can be replaced by "true [IF]". Any computed flag which may not be well-formed can be converted to a well-formed flag using 0<> .

@gnuarm No, I made no suggestion that a well-formed flag be a requirement to other conditional branch words such as IF , WHILE , UNTIL. Such a proposal would have severe consequences for exisiting code and cannot be done so easily. It may be worth heading in that direction ultimately, but the present suggestion is more modest.

BerndPaysanavatar of BerndPaysan

It will likely confuse people when IF and [IF] differ in that IF takes an x and jumps on 0, where [IF] only takes a well-formed flag.

Forth is not a typechecking language, and as consequence, we don't demand well-formed flags as inputs.

KrishnaMyneniavatar of KrishnaMyneni

@BerndPaysan Yes, the possible confusion for programmers in the difference in behavior between [IF] and IF is a legitimate concern.

Standard Forth is not a type-checking language. However, it is a typed language; otherwise stack diagrams would simply consist of the number of cell operands before and after. The standard makes anathema words with a stack diagram such as ( flag -- ), both through exclusion of any standard words which take well-formed flag operands (although [IF] is probably an unintended exception), and via the language of A.3.1.3.1. That appears to me to be an extreme position.

I believe my suggestion and discussion about this is probably premature in connection with this proposal, since it likely deals with unintentional language in the standard. Therefore, the language should be fixed per intent and per common practice. I agree with @alextangent that, from a standards perspective, this makes sense for the current proposal.

gnuarmavatar of gnuarm

"@gnuarm No, I made no suggestion that a well-formed flag be a requirement to other conditional branch words such as IF , WHILE , UNTIL. Such a proposal would have severe consequences for exisiting code and cannot be done so easily. It may be worth heading in that direction ultimately, but the present suggestion is more modest."

@KrishnaMyneni Your present suggestion may be "more modest', but it is no less consequential for breaking existing code. Certainly it would not be "easy" to implement such a change. It is good that you retracted it.

AntonErtlavatar of AntonErtl

The committee accepted this proposal: Vote #16 12Y:0:0

Accepted

Klaus_Schleisiekavatar of Klaus_Schleisiek

This code is meant as a reference implementation for bracket_IF and friends:

\ ---------------------------------------------------------------------- \ @file : bracket_IF.fs \ ----------------------------------------------------------------------
\ Last change: KS 15.09.2023 19:45:47 \ @author: Klaus Schleisiek \ @copyright: public domain
\ Traditionally, string comparison has been used to process [IF]. \ This version uses FIND instead. \ Multiline comment * ... \ ... *\ has been added, because it is trivial. \ Conditional clauses may be commented out using (, , or * \ ----------------------------------------------------------------------

: ?EXIT ( flag -- ) postpone IF postpone EXIT postpone THEN ; immediate : case? ( n1 n2 -- n1 ff | tf ) over = dup IF nip THEN ;

Defer [ELSE] ( -- ) immediate

: [IF] ( flag -- ) ?EXIT postpone [ELSE] ; immediate : [THEN] ( -- ) ; immediate : [NOTIF] ( flag -- ) 0= postpone [IF] ; immediate : [IFDEF] ( <name> -- ) postpone [DEFINED] postpone [IF] ; immediate : [IFUNDEF] ( <name> -- ) postpone [DEFINED] postpone [NOTIF] ; immediate

\ ---------------------------------------------------------------------- \ NEXT-WORD returns the xt of a word in the search order. \ Words, which are not found, will be skipped. \ 0 will be returned when the end of file is reached. \ ---------------------------------------------------------------------- : next-word ( -- xt | 0 ) BEGIN BEGIN BL word dup c@ WHILE find ?EXIT drop REPEAT drop refill 0= UNTIL 0 ; : *\ ( -- ) ; immediate \ end of multi-line comment : * ( -- ) BEGIN next-word dup 0= swap ['] *\ = or UNTIL ; immediate

Variable Nestlevel 0 Nestlevel ! \ nesting level counter

: nest ( -- ) 1 Nestlevel +! ; : unnest ( -- ) Nestlevel @ 1 - 0 max Nestlevel ! ; \ don't decrement below zero

: [if]-decode ( xt -- flag ) ['] [IF] case? IF nest false EXIT THEN ['] [NOTIF] case? IF nest false EXIT THEN ['] [IFDEF] case? IF nest false EXIT THEN ['] [IFUNDEF] case? IF nest false EXIT THEN ['] [ELSE] case? IF Nestlevel @ 0= EXIT THEN ['] [THEN] case? IF Nestlevel @ 0= unnest EXIT THEN ['] \ case? IF postpone \ false EXIT THEN \ needed to be able to e.g. comment out [THEN] ['] ( case? IF postpone ( false EXIT THEN \ needed to be able to e.g. comment out [THEN] ['] * case? IF postpone * false EXIT THEN \ needed to be able to e.g. comment out [THEN] 0= abort" [THEN] missing" \ end-of-file reached? \ all oter xt's are ignored false ; :noname ( -- ) BEGIN next-word [if]-decode UNTIL ; IS [ELSE]

Reply New Version